void ReportError(int err, LPCSTR szContext, LPCTSTR pszPath) { BPRINT_BUFFER & bp = *g_pbpErr; bprint_EndLine(bp); bprint(bp, szContext); if (pszPath) { bprint_Sep(bp, ' '); bprint(bp, pszPath); } bprint_Sep(bp, ' '); bprint(bp, TEXT("Failed : ")); bprint_AppendErrorText(bp, err); bprint_EndLine(bp); }
static void __cdecl bprintfl(BPRINT_BUFFER & bp, LPCTSTR pszFormat, ...) { va_list va; va_start(va, pszFormat); int cch = bvprintf(bp, pszFormat, va); va_end(va); bprint_EndLine(bp); }
void bprint_Terminate(BPRINT_BUFFER & bp, bool fFlush) { if (fFlush) bprint_EndLine(bp); if (bp.psz) { LocalFree(bp.psz); bp.psz = NULL; } }
void App_Cleanup(bool fFlush) { bprint_Terminate(fFlush); if (g_bprintErr.hOut) { if (fFlush) bprint_EndLine(g_bprintErr); if (g_bprintErr.hOut != GetStdHandle(STD_ERROR_HANDLE)) CloseHandle(g_bprintErr.hOut); g_bprintErr.hOut = NULL; } bprint_Terminate(g_bprintErr, false); }
int InitOwnerSid(BOOL fDiagnostic, BPRINT_BUFFER *pbp) { int err = 0; if ( ! ls.OwnerSid) { LPVOID pvInfo = NULL; DWORD cbSize = 0; if ( ! GetTokenInformation(ls.hToken, TokenOwner, NULL, 0, &cbSize)) { err = GetLastError(); if (ERROR_INSUFFICIENT_BUFFER == err) { err = 0; pvInfo = LocalAlloc(LPTR, cbSize); if ( ! pvInfo) { err = ERROR_OUTOFMEMORY; } else if ( ! GetTokenInformation(ls.hToken, TokenOwner, pvInfo, cbSize, &cbSize)) { err = GetLastError(); ReportError(err, "GetTokenInformation(TokenOwner)"); } else { err = 0; const TOKEN_OWNER * pOwner = (const TOKEN_OWNER *)pvInfo; ls.OwnerSid = pOwner->Owner; if (fDiagnostic) { bprintf(*pbp, TEXT("Got Owner Sid ")); PrintSidName(ls.OwnerSid, *pbp); bprint_Sep(*pbp, ' '); PrintSidText(ls.OwnerSid, *pbp); bprint_EndLine(*pbp); } } } } } return err; }
__inline bool bprint_Flush(BPRINT_BUFFER & bp) { return bprint_EndLine(bp); }
static void __cdecl bprintl(BPRINT_BUFFER & bp, LPCTSTR psz) { bprint(bp, psz); bprint_EndLine(bp); }
static int RecursiveDeleteDirectory(LPCTSTR pszPathIn, DWORD fdwFlags) { BPRINT_BUFFER & bp = *g_pbpDiag; DeletePathData dpd; ZeroMemory(&dpd, sizeof(dpd)); dpd.pbp = &g_bpErr; //this is for traversal testing... //dpd.fNoDelete = true; fdwFlags |= TDT_DIRLAST; // So we get directory callbacks after children have been deleted. // if the path isn't too long, convert to canonical form. for long paths // they has better provide canonical form to begin with. // TCHAR szCanonPath[MAX_PATH+1]; LPCTSTR pszPath = pszPathIn; if (lstrlen(pszPathIn) < MAX_PATH) { if (PathCanonicalize(szCanonPath, pszPathIn)) pszPath = szCanonPath; if (PathIsRelative(pszPath)) return ERROR_INVALID_PARAMETER; } // the unicode versions of the windows file api's can handle very long // path names if they are canonical and if they are preceeded by \\?\. // if we are build unicode, take advantage of that capability. static const WCHAR szPre[]= L"\\\\?\\"; WCHAR szFullPath[MAX_PATH + NUMCHARS(szPre)]; WCHAR * pszFullPath = szFullPath; WCHAR * pszFilePart = NULL; lstrcpyW(szFullPath, szPre); MultiByteToWideChar(CP_ACP, 0, pszPath, -1, szFullPath + NUMCHARS(szPre)-1, MAX_PATH); /* UINT cchFullPath = GetFullPathNameW(pszPath, MAX_PATH, szFullPath + NUMCHARS(szPre)-1, &pszFilePart); if (cchFullPath >= NUMCHARS(szFullPath)-1) { pszFullPath = (TCHAR *)LocalAlloc(LPTR, (cchFullPath + NUMCHARS(szPre) + 2) * sizeof(WCHAR)); if (pszFullPath) { lstrcpyW(pszFullPath, szPre); if (GetFullPathNameW(pszPath, cchFullPath+2, pszFullPath + NUMCHARS(szPre)-1, &pszFilePart) <= cchFullPath+2) pszPath = pszFullPath; } } else pszPath = szFullPath; */ int err = 0; DWORD fdwFileAttributes = GetFileAttributesW(szFullPath); if (INVALID_FILE_ATTRIBUTES == fdwFileAttributes) { fdwFileAttributes = 0; err = GetLastError(); ReportError(err, "Could not get attributes for ", pszPath); return err; } const bool fIsDir = (fdwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; if (fdwFlags & TDT_DIAGNOSTIC) bprintfl(bp, TEXT("Delete %s 0x%04X %s\\*"), fIsDir ? TEXT("Directory") : TEXT("File"), fdwFlags, pszPath); if (fIsDir) { err = TraverseDirectoryTreeW(szFullPath, L"*", fdwFlags, DeletePathCallback, &dpd, 0); if ( ! err || (fdwFlags & TDT_CONTINUE)) { bprint_EndLine(bp); if ( ! dpd.fNoDelete && ! RemoveDirectoryW(szFullPath)) { bprint_EndLine(bp); err = GetLastError(); ReportError(err, "RemoveDirectory", pszPath); } } } else // initial path is a file, not a directory. { if ( ! dpd.fNoDelete && ! DeleteFileW(szFullPath)) { bprint_EndLine(bp); err = GetLastError(); ReportError(err, "DeleteFile", pszPath); } } bprint_EndLine(bp); return err; }
static bool WINAPI DeletePathCallback ( VOID * pvUser, LPCWSTR pszPath, // path and filename, may be absolute or relative. int ochName, // offset from start of pszPath to first char of the file/dir name. DWORD fdwFlags, int cDepth, int ixItem, const WIN32_FIND_DATAW & wfd) { DeletePathData & dpd = *(DeletePathData*)pvUser; if (dpd.fAborting) return false; BPRINT_BUFFER & bp = *dpd.pbp; const bool fDirectory = (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; const bool fProtected = (wfd.dwFileAttributes & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)) != 0; dpd.cTotalVisited += 1; if (fDirectory) dpd.cDirsVisited += 1; else dpd.cFilesVisited += 1; dpd.cLastDepth = cDepth; dpd.cMaxDepth = max(cDepth, dpd.cMaxDepth); if (fProtected) { // build attributes flags that don't contain readonly or system (or hidden) DWORD fdwAttr = wfd.dwFileAttributes & (FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_ATTRIBUTE_TEMPORARY); if ((fdwFlags & TDT_DIAGNOSTIC) || dpd.fDiagnostic) bprintfl(*dpd.pbp, TEXT("Clearing%s%s attrib(s) from %s"), (wfd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) ? TEXT(" SYS") : TEXT(""), (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? TEXT(" RO") : TEXT(""), pszPath); if ( ! SetFileAttributesW(pszPath, fdwAttr)) { int err = GetLastError(); if (ERROR_ACCESS_DENIED == err) { int errT = RemoveFileDACLs(pszPath, dpd.fDiagnostic, dpd.pbp); if (errT) err = errT; else if (SetFileAttributesW(pszPath, fdwAttr)) err = 0; else err = GetLastError(); } } } if (fdwFlags & TDT_FIRST) dpd.fDirAlreadyTriedDACLRemove = false; bprint_EndLine(bp); int err = ERROR_SUCCESS; if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { // When we get the DIRLAST callback, it should be after we have deleted all of the children. // NOW we can try and remove the directory. // if (fdwFlags & TDT_DIRLAST) { err = DpdRemoveDirectory(pszPath, ochName, dpd, dpd.fDiagnostic, DPD_F_REMOVEDACLS); } } else { err = DpdDeleteFile(pszPath, ochName, dpd, dpd.fDiagnostic, DPD_F_REMOVEDACLS); } if (err && ! (fdwFlags & TDT_CONTINUE)) { bprint_EndLine(bp); if (dpd.fDiagnostic) bprintl(bp, "Aborting."); dpd.fAborting = true; return false; } bprint_EndLine(bp); return true; }
int DeletePath(LPCTSTR pszPathIn, LPCTSTR pszPattern, DWORD fdwTraverse, DWORD fdwSecurity, DWORD fdwVerbose, BPRINT_BUFFER & bp) { DWORD fdwFlags = fdwTraverse & (TDT_INPUTMASK & ~TDT_USERMASK); if (fdwVerbose & DP_V_VERBOSE) fdwFlags |= TDT_USER_F_VERBOSE; if (fdwVerbose & DP_V_DIAGNOSTIC) fdwFlags |= TDT_DIAGNOSTIC; bool fQuiet = (fdwVerbose & DP_V_QUIET) != 0; DeletePathData lad; ZeroStruct(&lad); lad.pbp = &bp; if (fdwSecurity & DP_S_NODELETE) lad.fNoDelete = true; fdwFlags |= TDT_DIRLAST; // So we get directory callbacks after children have been deleted. // if the path isn't too long, convert to canonical form. for long paths // they has better provide canonical form to begin with. // TCHAR szCanonPath[MAX_PATH+1]; LPCTSTR pszPath = pszPathIn; if (lstrlen(pszPathIn) < MAX_PATH && PathCanonicalize(szCanonPath, pszPathIn)) { pszPath = szCanonPath; } // the unicode versions of the windows file api's can handle very long // path names if they are canonical and if they are preceeded by \\?\. // if we are build unicode, take advantage of that capability. #ifdef UNICODE static const TCHAR szPre[]= TEXT("\\\\?\\"); TCHAR szFullPath[MAX_PATH + NUMCHARS(szPre)]; TCHAR * pszFullPath = szFullPath; TCHAR * pszFilePart = NULL; lstrcpy(szFullPath, szPre); UINT cchFullPath = GetFullPathName(pszPath, MAX_PATH, szFullPath + NUMCHARS(szPre)-1, &pszFilePart); if (cchFullPath >= NUMCHARS(szFullPath)-1) { pszFullPath = (TCHAR *)LocalAlloc(LPTR, (cchFullPath + NUMCHARS(szPre) + 2) * sizeof(TCHAR)); if (pszFullPath) { lstrcpy(pszFullPath, szPre); if (GetFullPathName(pszPath, cchFullPath+2, pszFullPath + NUMCHARS(szPre)-1, &pszFilePart) <= cchFullPath+2) pszPath = pszFullPath; } } else pszPath = szFullPath; #endif int err = 0; DWORD fdwFileAttributes = GetFileAttributes(pszPath); if (INVALID_FILE_ATTRIBUTES == fdwFileAttributes) { fdwFileAttributes = 0; err = GetLastError(); ReportError(err, "Could not get attributes for ", pszPath); return err; } const bool fIsDir = (fdwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; if (fdwFlags & TDT_DIAGNOSTIC) bprintfl(bp, TEXT("Delete %s 0x%04X %s\\%s"), fIsDir ? TEXT("Directory") : TEXT("File"), fdwFlags, pszPath, pszPattern); if (fIsDir) { if (fdwTraverse & TDT_SUBDIRS) { if ( ! pszPattern || ! pszPattern[0]) err = TraverseDirectoryTree(pszPath, TEXT("*"), fdwFlags, DeletePathCallback, &lad, 0); else err = TraverseDirectoryTree(pszPath, pszPattern, fdwFlags, DeletePathCallback, &lad, 0); } if ( ! err || (fdwFlags & TDT_CONTINUE)) { bprint_EndLine(bp); if ( ! (fdwTraverse & TDT_NODIRS) && (!pszPattern || !pszPattern[0])) { if ( ! fQuiet) { bprint(bp, lad.fNoDelete ? TEXT("NoRemove ") : TEXT("Removing ")); bprint(bp, pszPath); } if ( ! lad.fNoDelete && ! RemoveDirectory(pszPath)) { bprint_EndLine(bp); err = GetLastError(); ReportError(err, "RemoveDirectory", pszPath); if ( ! (fdwFlags & TDT_CONTINUE)) if ( ! fQuiet) bprintl(bp, "Aborting."); } } } } else // initial path is a file, not a directory. { if (fdwTraverse & TDT_SUBDIRS) { if ( ! pszPattern || ! pszPattern[0]) { err = TraverseDirectoryTree(pszPath, TEXT("*"), fdwFlags, DeletePathCallback, &lad, 0); } else { //#pragma REMIND("TJ: add code to split the file from the path and recurse on the filename.") } } if (fdwTraverse & TDT_NOFILES) { // Nothing to do. } else if ( ! pszPattern || ! pszPattern[0]) { if ( ! fQuiet) { bprint(bp, lad.fNoDelete ? TEXT("NoDelete ") : TEXT("Deleting ")); bprint(bp, pszPath); } if ( ! lad.fNoDelete && ! DeleteFile(pszPath)) { bprint_EndLine(bp); err = GetLastError(); ReportError(err, "DeleteFile", pszPath); if ( ! (fdwFlags & TDT_CONTINUE)) if ( ! fQuiet) bprintl(bp, "Aborting."); } } } bprint_EndLine(bp); return err; }