int bprintdbl(FILE *f,double d,uint precision) { int c = 0; llong val = 0; /* Note: this is probably not a really good way of converting IEEE754-floating point numbers * to string. But its simple and should be enough for my purposes :) */ if(isnan(d)) { if(d < 0) c += RETERR(bputc(f,'-')); c += RETERR(bputs(f,"nan",-1)); } else if(isinf(d)) { if(d < 0) c += RETERR(bputc(f,'-')); c += RETERR(bputs(f,"inf",-1)); } else { val = (llong)d; c += bprintl(f,val); d -= val; if(d < 0) d = -d; RETERR(bputc(f,'.')); c++; while(precision-- > 0) { d *= 10; val = (llong)d; RETERR(bputc(f,(val % 10) + '0')); d -= val; c++; } } return c; }
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; }