Esempio n. 1
0
static int WINAPI DpdDeleteFile (
   LPCWSTR          pszPath,
   int              ochName,
   DeletePathData & dpd,
   DWORD            fdwVerbose,
   DWORD            fdwFlags)
{
   int err = 0;
   if (dpd.fNoDelete)
      {
      if (fdwVerbose)
         bprintf(*dpd.pbp, TEXT("NoDelete %s "), pszPath);
      return 0;
      }

   if (fdwVerbose)
      bprintf(*dpd.pbp, TEXT("Deleting %s "), pszPath);

   if (DeleteFileW(pszPath))
      {
      dpd.cFilesDeleted += 1;
      }
   else
      {
      err = GetLastError();
      if ((ERROR_ACCESS_DENIED == err) && (fdwFlags & DPD_F_REMOVEDACLS))
         {
         if ( ! dpd.fDirAlreadyTriedDACLRemove && (ochName > 1))
            {
            LPWSTR pszParent = strdupW(pszPath);
            pszParent[ochName-1] = 0;
            //StrCopyN(szParent, NUMCHARS(szParent), pszPath, ochName);
            int errT = RemoveFileDACLs(pszParent, dpd.fDiagnostic, dpd.pbp);
            if (errT)
               err = errT;
            else if (DeleteFileW(pszPath))
               {
               err = 0;
               dpd.cFilesDeleted += 1;
               }
            else
               {
               err = GetLastError();
               }
            // dont try to remove dacls again for this directory.
            dpd.fDirAlreadyTriedDACLRemove = true;
            free(pszParent);
            }

         // the error _may_ have been cleared by the time we get here, if it hasn't
         // then try and remove dacls from the file, then try again to delete the file.
         //
         if (ERROR_ACCESS_DENIED == err)
            {
            int errT = RemoveFileDACLs(pszPath, dpd.fDiagnostic, dpd.pbp);
            if (errT)
               err = errT;
            else if (DeleteFileW(pszPath))
               {
               err = 0;
               dpd.cFilesDeleted += 1;
               }
            else
               {
               err = GetLastError();
               }
            }
         }

      if (err)
         {
         dpd.cDeleteFailures += 1;
         if (fdwVerbose)
            {
            bprint_Sep(*dpd.pbp, ' ');
            bprint_AppendErrorText(*dpd.pbp, err);
            }
         }
      }

   return err;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
int TraverseDirectoryTreeW (
   LPCWSTR pszPath, 
   LPCWSTR pszPattern, 
   DWORD   fdwFlags, 
   PFNTraverseDirectoryTreeCallbackW pfnCallback, 
   LPVOID  pvUser,
   int     nCurrentDepth)
{
   bool fSubdirs    = (fdwFlags & TDT_SUBDIRS) != 0;
   bool fDiagnostic = (fdwFlags & TDT_DIAGNOSTIC) != 0;
   //bool fDirFirst   = (fdwFlags & TDT_DIRFIRST) != 0;
   //bool fDirLast    = (fdwFlags & TDT_DIRLAST) != 0;

   if (fDiagnostic)
      {
      if (pszPattern)
         bprintfl(*g_pbpDiag, "TDT[%d]: %04x path = '%s' pattern = '%s' subdirs = %d", nCurrentDepth, fdwFlags, pszPath, pszPattern, fSubdirs);
      else
         bprintfl(*g_pbpDiag, "TDT[%d]: %04x path = '%s' pattern = NULL subdirs = %d", nCurrentDepth, fdwFlags, pszPath, fSubdirs);
      }

   // build a string containing path\pattern, we will pass this
   // into FindFirstFile. there are some special cases.
   // we treat paths that end in \ as meaning path\*.
   // we replace *.* with * since it means the same thing and
   // is easier to parse. (this is a special case go back to DOS). 
   //
   int cchPath = lstrlenW(pszPath);
   int cchMax = cchPath + MAX_PATH + 2;
   LPWSTR psz = (LPWSTR)malloc(cchMax * sizeof(WCHAR));
   lstrcpyW(psz, pszPath);
   LPWSTR pszNext = psz + lstrlenW(psz);

   bool fMatchAll = false;
   if (pszPattern && pszPattern[0])
      {
      if (0 == lstrcmpW(pszPattern, L"*.*") || 0 == lstrcmpW(pszPattern, L"*"))
         {
         fMatchAll = true;
         }
      pszNext = PathAddBackslashW(psz);
      lstrcpyW(pszNext, pszPattern);
      }
   else if (pszNext > psz && (pszNext[-1] == '\\' || pszNext[-1] == '/'))
      {
      fMatchAll = true;
      pszNext[0] = '*';
      pszNext[1] = 0;
      }

   HRESULT hr = S_OK;
   int err = ERROR_SUCCESS;
   int ixCurrentItem = 0;
   DWORD dwFirst = TDT_FIRST;

   LinkedFindData * pdirs = NULL;

   WIN32_FIND_DATAW wfd;
   HANDLE hFind = FindFirstFileW(psz, &wfd);
   if (INVALID_HANDLE_VALUE == hFind) 
      {
      err = GetLastError();
      // if we can't open the directory because of an access denied error
      // it might be the DACLs that are causing the problem. If so, then
      // just remove the dacls. we are going to be deleting the directory
      // anway...
      //
      if (ERROR_ACCESS_DENIED == err)
         {
         int errT = RemoveFileDACLs(pszPath, fdwFlags & TDT_DIAGNOSTIC, g_pbpDiag);
         if (errT)
            err = errT;
         else
            {
            hFind = FindFirstFileW(psz, &wfd);
            if (INVALID_HANDLE_VALUE == hFind) 
               {
               errT = GetLastError();
               if (errT != err)
                  ReportErrorW(errT, "FindFirstFile ", psz);
               }
            else
               {
               err = 0;
               }
            }
         }
      if (err)
         ReportErrorW(err, "FindFirstFile ", psz);
      }

   if (hFind && INVALID_HANDLE_VALUE != hFind)
      {
      do {
         // ignore . and ..
         if (IsDotOrDotDot(wfd.cFileName))
            continue;

         ++ixCurrentItem;

         bool fSkip = false;
         if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            {
            // if we are recursing, and we happen to be matching all, then remember this
            // directory for later (so we don't need to enumerate again for dirs).
            // otherwise we will have to re-enumerate in this directory to get subdirs.
            if (fSubdirs && fMatchAll) 
               {
               LinkedFindData * pdir = (LinkedFindData*)malloc(sizeof(LinkedFindData));
               pdir->wfd = wfd;
               pdir->next = pdirs;
               pdirs = pdir;
               fSkip = true;  // we will do the callback for this directory later, if at all.
               }
            else if (fdwFlags & TDT_NODIRS)
               fSkip = true;
            }
         else
            {
            if (fdwFlags & TDT_NOFILES)
               fSkip = true;
            }

         if (fDiagnostic)
            bprintfl (*g_pbpDiag, "TDT[%d]: 0x%08x %s %s", nCurrentDepth, wfd.dwFileAttributes, wfd.cFileName, fSkip ? "<skip>" : "");

         if ( ! fSkip)
            {
            lstrcpyW(pszNext, wfd.cFileName); 
            if ( ! pfnCallback(pvUser, psz, pszNext - psz, (fdwFlags & ~(TDT_DIRLAST | TDT_DIRFIRST)) | dwFirst, nCurrentDepth, ixCurrentItem, wfd))
               break;
            dwFirst = 0;
            }

         } while (FindNextFileW(hFind, &wfd));

         if (fDiagnostic)
            bprintfl (*g_pbpDiag, "TDT[%d]: Done with %s %s", nCurrentDepth, pszPath, pszPattern);
      }

   // we want to traverse subdirs, but we were unable to build a list of dirs when we 
   // enumerated the files, so re-enumerate with * to get the directories.
   if (fSubdirs && ! fMatchAll)
      {
      if (hFind && INVALID_HANDLE_VALUE != hFind)
         FindClose(hFind);

      lstrcpyW(pszNext, L"*");
      hFind = FindFirstFileW(psz, &wfd);
      if (INVALID_HANDLE_VALUE != hFind) 
         {
         do {
            if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && ! IsDotOrDotDot(wfd.cFileName))
               {
               LinkedFindData * pdir = (LinkedFindData*)malloc(sizeof(LinkedFindData));
               pdir->wfd = wfd;
               pdir->next = pdirs;
               pdirs = pdir;
               }

            } while (FindNextFileW(hFind, &wfd));
         }
      }

   err = GetLastError();
   if (ERROR_NO_MORE_FILES == err)
      err = ERROR_SUCCESS;

   // now traverse and callback subdirectories.
   //
   if (fSubdirs && pdirs)
      {
      pdirs = ReverseLinkedList(pdirs);
      while (pdirs)
         {
         LinkedFindData * pdir = pdirs;
         pdirs = pdirs->next;

         lstrcpyW(pszNext, pdir->wfd.cFileName); 
         if ((fdwFlags & TDT_DIRFIRST) && ! (fdwFlags & TDT_NODIRS))
            {
            if (fDiagnostic)
               bprintfl (*g_pbpDiag, "TDT[%d]: DIRFIRST 0x%08x %s %s", nCurrentDepth, pszPath, pszPattern);

            if ( ! pfnCallback(pvUser, psz, pszNext - psz, TDT_DIRFIRST | (fdwFlags & ~TDT_DIRLAST) | dwFirst, nCurrentDepth, ixCurrentItem, pdir->wfd))
               break;
            dwFirst = 0;
            }

         err = TraverseDirectoryTreeW(psz, pszPattern, fdwFlags, pfnCallback, pvUser, nCurrentDepth+1);

         if ((fdwFlags & TDT_DIRLAST) && ! (fdwFlags & TDT_NODIRS))
            {
            if (fDiagnostic)
               bprintfl (*g_pbpDiag, "TDT[%d]: DIRLAST 0x%08x %s %s", nCurrentDepth, pszPath, pszPattern);

            if ( ! pfnCallback(pvUser, psz, pszNext - psz, TDT_DIRLAST | (fdwFlags & ~TDT_DIRFIRST) | dwFirst, nCurrentDepth, ixCurrentItem, pdir->wfd))
               break;
            dwFirst = 0;
            }
         }
      }


   if (hFind && INVALID_HANDLE_VALUE != hFind)
      FindClose(hFind);

   return err;
}
Esempio n. 4
0
static int WINAPI DpdRemoveDirectory (
   LPCTSTR          pszPath,
   int              ochName,
   DeletePathData & dpd,
   DWORD            fdwVerbose,
   DWORD            fdwFlags)
{
   int err = 0;
   if (dpd.fNoDelete)
      {
      if (fdwVerbose)
         bprintf(*dpd.pbp, TEXT("NoRemove %s "), pszPath);
      return 0;
      }

   if (fdwVerbose)
      bprintf(*dpd.pbp, TEXT("Removing %s "), pszPath);

   if (RemoveDirectory(pszPath))
      {
      dpd.cDirsRemoved += 1;
      }
   else
      {
      err = GetLastError();
      if ((ERROR_ACCESS_DENIED == err) && (fdwFlags & DPD_F_REMOVEDACLS))
         {
         if ( ! dpd.fDirAlreadyTriedDACLRemove && (ochName > 1))
            {
            TCHAR szParent[MAX_PATH];
            StrCopyN(szParent, NUMCHARS(szParent), pszPath, ochName);
            int errT = RemoveFileDACLs(szParent, fdwVerbose & (TDT_DIAGNOSTIC | TDT_USER_F_VERBOSE), dpd.pbp);
            if (errT)
               err = errT;
            else if (RemoveDirectory(pszPath))
               {
               err = 0;
               dpd.cDirsRemoved += 1;
               }
            else
               {
               err = GetLastError();
               }
            // dont try to remove dacls again for this directory.
            dpd.fDirAlreadyTriedDACLRemove = true;
            }

         // the error _may_ have been cleared by the time we get here, if it hasn't
         // then try and remove dacls from the file, then try again to delete the file.
         //
         if (ERROR_ACCESS_DENIED == err)
            {
            int errT = RemoveFileDACLs(pszPath, fdwVerbose & (TDT_DIAGNOSTIC | TDT_USER_F_VERBOSE), dpd.pbp);
            if (errT)
               err = errT;
            else if (RemoveDirectory(pszPath))
               {
               err = 0;
               dpd.cDirsRemoved += 1;
               }
            else
               {
               err = GetLastError();
               }
            }
         }

      if (err)
         {
         dpd.cRemoveFailures += 1;
         if (fdwVerbose)
            {
            bprint_Sep(*dpd.pbp, ' ');
            bprint_AppendErrorText(*dpd.pbp, err);
            }
         }
      }
   return err;
}