예제 #1
0
파일: main.cpp 프로젝트: bbockelm/htcondor
static HRESULT CALLBACK OpenList_Open (
   POPENLIST_FILE polf,
   LPARAM         lArgs)
{
   HRESULT hr = S_OK;

   if (E_CANCEL != polf->hr)  // Possible if a queue'd open was canceled on progman and we are being called for possible batch undo handling
      {
      hr = E_FILE_UNSUPPORTED;

      if (g_app.fDiagnostic)
         bprintfl("\nDeletePath \"%s\" recursive = %d", polf->szPathName, g_app.fSubDirs);

      DWORD fdwTraverse = 0;
      if (g_app.fSubDirs)     fdwTraverse |= TDT_SUBDIRS;
      //if (g_app.fNoFiles)   fdwTraverse |= TDT_NOFILES;
      //if (g_app.fNoDirs)    fdwTraverse |= TDT_NODIRS;
      if (g_app.fContinue)    fdwTraverse |= TDT_CONTINUE;
      if (g_app.fDiagnostic)  fdwTraverse |= TDT_DIAGNOSTIC;

      DWORD fdwSecurity = 0;
      if (g_app.fNoDelete) fdwSecurity = DP_S_NODELETE;

      DWORD fdwVerbose = 0;
      if (g_app.fVerbose)     fdwVerbose |= DP_V_VERBOSE;
      if (g_app.fDiagnostic)  fdwVerbose |= DP_V_DIAGNOSTIC;
      if (g_app.fQuiet)       fdwVerbose |= DP_V_QUIET;

      int err = DeletePath(polf->szPathName, TEXT(""), fdwTraverse, fdwSecurity, fdwVerbose, g_bprint);

      //  DeletePath has already reported errors.
      /*
      if (err && ERROR_NO_MORE_FILES != err)
         {
         TCHAR szErr[MAX_PATH];
         if (GetLastErrorText(err, szErr, NUMCHARS(szErr)) <= 0)
            wsprintf(szErr, TEXT("Error %d"), err);
         bprintfl ("%s\n", szErr);
         }
      */
      if (g_app.fContinue)
         hr = S_OK;
      else if (err)
         hr = E_CANCEL;
      }

   return hr;
}
예제 #2
0
파일: main.cpp 프로젝트: bbockelm/htcondor
int __cdecl main()
{
   HRESULT hr = App_Early_Initialize();
   if (SUCCEEDED(hr))
      {
      hr = App_ExecuteCommandLine (GetCommandLine(), TRUE);
      if (FAILED(hr))
         g_app.fUsage = TRUE;
      }

   if (g_app.fShowLogo || g_app.fUsage)
      {
      LPCTSTR pszAppName = _pszModuleName;
      bprintfl("%s version 1.0.0 Built " __DATE__ __TIME__, pszAppName);
      }

   if (g_app.fUsage)
      {
      LPCTSTR pszAppName = _pszModuleName;

      bprintf("\nusage: %s [/? | /HELP] [@{argfile}] [args] <dir>\n\n", pszAppName);
      bprintf("  remove directory <dir>, taking ownership and removing\n");
      bprintf("  ACLs as necessary. Where [args] is one or more of\n\n");

      for (int ii = 0; ii < NUMELMS(g_aAppCommands); ++ii)
         {
         CMDTABLE * pCmd = &g_aAppCommands[ii];
         if ( ! pCmd->pszName)
            break;
         LPCTSTR pszCmd = pCmd->pszName;
         TCHAR szCmd[128];
         if (pCmd->cmd.cParams > 0)
            {
            StrCopy(szCmd, pCmd->pszName, NUMCHARS(szCmd));
            int cch = StrLen(szCmd);
            szCmd[cch++] = ':';
            StrCopy(szCmd+cch, pCmd->pszArgType, NUMCHARS(szCmd)-cch);
            pszCmd = szCmd;
            }
         bprintf("  /%-16s", pszCmd);
         bprintf("  %s\n", pCmd->pszUsage);
         }
      }

   App_Cleanup(SUCCEEDED(hr));
   return (int)hr;
}
예제 #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;
}
예제 #4
0
파일: main.cpp 프로젝트: bbockelm/htcondor
HRESULT App_CookArgList (
   HCMDLIST * phlst,
   LPCTSTR    aArgs[],
   UINT       ixFirst,  // first arg to execute
   UINT       cArgs)    // count of args to execute
{
   HRESULT    hr = S_FALSE; // there were no args...
   TCHAR      szTempArg[64]; // temp if we need to copy and arg

   HCMDLIST   hlst;

   *phlst = NULL;
   hr = Vector_Create(&hlst, cArgs, -1);
   if (FAILED(hr))
      return hr;

   // look at args, parsing switches and building up the array of filename pointers
   //
   UINT ixLast = (ixFirst + cArgs);
   for (UINT ii = ixFirst; ii < ixLast; ++ii)
      {
      LPCTSTR pszArg = aArgs[ii];
      if ( ! pszArg)
         break;

      // assume a file open command.
      //
      hr = S_OK;
      CMDSWITCH cmd = {APP_CMD_PATH, 0, 1, NULL};

      // if the first character of the arg is an '@', what follows should be a command file.
      //
      if (pszArg[0] == '@')
         {
         // command will be an argfile command
         //
         cmd.idCmd     = APP_CMD_ARGFILE;
         cmd.cParams   = 1;    // on arg needed
         cmd.pszParams = NULL; // no default

         // if next character is not a 0, it must be the filename
         // otherwise, suck up the next token and use it as the filename.
         //
         pszArg = StrCharNext (pszArg); // skip '@'
         if (0 != pszArg[0])
            {
            cmd.pszParams = pszArg;
            }
         else if (ii+1 < ixLast) // next pszArg belongs to us..
            {
            LPCTSTR pszT = aArgs[ii+1];
            if ('-' != pszT[0] && '/' != pszT[0])
               {
               cmd.pszParams = pszT;
               ++ii;  // advance the loop counter.
               }
            }
         }
      else if ('-' == pszArg[0] || '/' == pszArg[0])
         {
         pszArg = StrCharNext (pszArg);
         if (0 == pszArg[0])
            {
            hr = E_INVALIDARG;
            goto bail;
            }

         // look for a ':' in the arg, and
         //
         LPCTSTR psz = StrCharNext(pszArg);
         LPCTSTR pszParam = NULL;
         while (0 != psz[0])
            {
            // if the arg contains a colon, set pszParam to point to it
            // and extract the stuff before the colon as the actual arg.
            //
            if (':' == psz[0])
               {
               pszParam = StrCharNext (psz);
               UINT cch = (UINT)(((LPARAM)psz - (LPARAM)pszArg) / NUMBYTES(TCHAR));
               StrCopyN (szTempArg, NUMCHARS(szTempArg), pszArg, cch + 1);
               DASSERT(0 == szTempArg[min(NUMCHARS(szTempArg)-1, cch)]);
               pszArg = szTempArg;
               break;
               }

            psz = StrCharNext(psz);
            }

         // lookup the argment
         //
         if ( ! App_LookupCmdLineArg (g_aAppCommands, pszArg, &cmd))
            {
            bprintfl("%s is not a valid argument", pszArg);
            hr = E_INVALIDARG;
            goto bail;
            }

         if (pszParam)
            {
            if (cmd.cParams < 1)
               {
               // if we have a param, but the arg doesn't take any, bail.
               //
               bprintfl("the %s argument is does not take parameters", pszArg);
               hr = E_INVALIDARG;
               goto bail;
               }

            cmd.pszParams = pszParam;
            }
         else
            {
            // if the command needs args, but none have been found so
            // far, try sucking up the next token in the command line
            //
            if (cmd.cParams > 0 && NULL == cmd.pszParams)
               {
               if (ii+1 < ixLast) // next pszArg belongs to us..
                  {
                  LPCTSTR pszT = aArgs[ii+1];
                  if ('-' != pszT[0] && '/' != pszT[0])
                     {
                     cmd.pszParams = pszT;
                     ++ii;  // advance the loop counter.
                     }
                  }
               }
            }
         }
      else
         {
         // not a switch, this is an implied file-open command
         //
         cmd.pszParams = pszArg;
         }

      // if the command needs an arg, but we dont have one.
      // the command line is in error.
      //
      if ((cmd.cParams > 0) && (NULL == cmd.pszParams))
         {
         bprintfl("the %s argument requires parameters", pszArg);
         g_app.fUsage = true;
         hr = E_INVALIDARG;
         goto bail;
         }

      // append the command.
      //
      Vector_AppendItem(hlst, cmd);
      }

   // return the command list
   //
   *phlst = hlst;

bail:
   if (FAILED(hr) || Vector_GetCountSafe(hlst) < 1)
      {
      *phlst = NULL;
      if (hlst)
         Vector_Delete (hlst);
      }
   return hr;
}
예제 #5
0
int RemoveFileDACLs(LPCWSTR pszPath, BOOL fDiagnostic, BPRINT_BUFFER *pbp)
{
   //
   // make sure that we have ESE_SECURITY priviledge
   //
   int err = 0;
   if ( ! AddLocalPrivilege(ESE_SECURITY))
      {
      err = GetLastError();
      if (fDiagnostic)
         ReportError(err, "AdjustTokenPrivileges");
      }

   // setup globals, this do nothing if this is not the first time
   // this function was called. 
   //
   InitStandardSids(fDiagnostic, pbp);
   //InitUserSid(fDiagnostic, pbp);
   InitOwnerSid(fDiagnostic, pbp);

   //
   // Attempt to put a NULL Dacl on the file/directory
   //
   SECURITY_DESCRIPTOR si;
   ZeroMemory(&si, sizeof(si));
   InitializeSecurityDescriptor(&si, SECURITY_DESCRIPTOR_REVISION);
   MSC_SUPPRESS_WARNING(6248) // warning: setting the DACL to null will result in unprotected object...
   SetSecurityDescriptorDacl (&si,  TRUE, NULL, FALSE);

   if ( ! SetFileSecurityW(pszPath, DACL_SECURITY_INFORMATION, &si))
      {
      err = GetLastError();
      if (fDiagnostic)
         ReportErrorW (err, "SetFileSecurity(DACL)[1] ", pszPath);
      }
   else
      {
      if (fDiagnostic)
         {
         if (bprint_IsEmpty(*pbp))
            bprintfl(*pbp, "DACLs removed from %s", pszPath);
         else
            bprint(*pbp, " DACLs removed");
         }
      return 0;
      }

   //
   // Attempt to make take ownership of the file.
   //

   SetSecurityDescriptorOwner (&si, ls.OwnerSid, FALSE);

   if (SetFileSecurityW(pszPath, OWNER_SECURITY_INFORMATION, &si))
      err = 0;
   else
      {
      err = GetLastError();
      if (fDiagnostic)
         ReportErrorW (err, "SetFileSecurity(Owner)[1] ", pszPath);

      //ZeroMemory(&si,sizeof(si));
      //InitializeSecurityDescriptor(&si, SECURITY_DESCRIPTOR_REVISION);
      //SetSecurityDescriptorOwner (&si, ls.OwnerSid, FALSE);

      if ( ! AddLocalPrivilege(ESE_TAKE_OWNERSHIP))
         {
         static bool fReportedSeTakeOwner = false;
         if (fDiagnostic && ! fReportedSeTakeOwner)
            {
            ReportErrorW(GetLastError(), "SeTakeOwnership ", pszPath);
            fReportedSeTakeOwner = true;
            }
         }
      else if ( ! SetFileSecurityW(pszPath, OWNER_SECURITY_INFORMATION, &si))
         {
         err = GetLastError();
         if (fDiagnostic)
            ReportErrorW (err, "SetFileSecurity(Owner)[2] ", pszPath);
         }
      else
         {
         err = 0;
         }
      }

   // if we successfully took ownership, try again to set a NULL DACL 
   //
   if ( ! err)
      {
      if (fDiagnostic)
         {
         if (bprint_IsEmpty(*pbp))
            bprintfl(*pbp, "Ownership taken of %s", pszPath);
         else
            bprint(*pbp, " Ownership taken");
         }

      if ( ! SetFileSecurityW(pszPath, DACL_SECURITY_INFORMATION, &si))
         {
         err = GetLastError();
         if (fDiagnostic)
            ReportErrorW (err, "SetFileSecurity(DACL)[2] ", pszPath);
         }
      else
         {
         if (fDiagnostic)
            {
            if (bprint_IsEmpty(*pbp))
               bprintfl(*pbp, "DACLs removed from %s", pszPath);
            else
               bprintfl(*pbp, " DACLs removed", pszPath);
            }
         return 0;
         }
      }

   return err; 
}
예제 #6
0
bool AddLocalPrivilege(int ePriv)
{
   if (ePriv < 0 || ePriv >= NUMELMS(g_aPrivs))
      {
      ASSERT(!"unsupported priv requested");
      return false;
      }

   if ( ! ls.hToken)
      {
      if ( ! OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, TRUE, &ls.hToken))
         {
         if (GetLastError() == ERROR_NO_TOKEN)
            {
            if ( ! OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &ls.hToken))
               return false;
            }
         else
            return false;
         }
      }

   // have we queried this already?
   if (ls.aCurr[ePriv].Luid.LowPart || ls.aCurr[ePriv].Luid.HighPart)
      {
      return (ls.aCurr[ePriv].Attributes & SE_PRIVILEGE_ENABLED) != 0;
      }

   PLUID pluid = &g_aPrivs[ePriv].luid;
   if ( ! pluid->LowPart && ! pluid->HighPart &&
        ! LookupPrivilegeValue(NULL, g_aPrivs[ePriv].psz, &g_aPrivs[ePriv].luid))
      {
      return false;
      }

   TOKEN_PRIVILEGES tp = {1};
   tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
   tp.Privileges[0].Luid       = *pluid;

   TOKEN_PRIVILEGES tpOrig = {1};
   tpOrig.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
   tpOrig.Privileges[0].Luid       = *pluid;

   //
   // enable or disable the privilege
   //
   DWORD cb = sizeof(tpOrig);
   if ( ! AdjustTokenPrivileges(ls.hToken, FALSE, &tp, cb, &tpOrig, &cb))
      {
      bprintfl(*g_pbpDiag, " %d passed, %d needed", sizeof(tpOrig), cb);
      return false;
      }


   ls.aOrig[ePriv].Luid       = tpOrig.Privileges[0].Luid;
   ls.aOrig[ePriv].Attributes = tpOrig.Privileges[0].Attributes;
   ls.aCurr[ePriv].Luid       = tp.Privileges[0].Luid;
   ls.aCurr[ePriv].Attributes = tp.Privileges[0].Attributes;


   return true;
}
예제 #7
0
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;
}
예제 #8
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;
}
예제 #9
0
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;
}