Finding the Recycle Bin on a local NTFS drive

前端 未结 4 2139
我寻月下人不归
我寻月下人不归 2021-01-03 09:33

I\'m trying to write some simple code that will return the directory for the recycle bin on a local drive. Seems like it would be simple -- should be a thousand answers on

4条回答
  •  旧巷少年郎
    2021-01-03 10:05

    Using Raymond Chen's advice, and someone else's technique (can't remember where I found it) I present a function that will find the Recycle Bin directory on a drive. The function cycles through the directories in the root directory looking at hidden and/or system directories. When it finds one, it checks the child subdirectories looking for one that has CLSID_Recycle Bin.

    Note that I've included two GetFolderCLSID functions below. Raymond Chen's is the simpler one, but it doesn't work on Windows 2000. The other implementation is longer, but appears to work everywhere.

    Call like: CString recycleDir = FindRecycleBinOnDrive(L"C:\");

    CString FindRecycleBinOnDrive(LPCWSTR path)
    {
        CString search;
        search.Format(L"%c:\\*", path[0]);
        WIN32_FIND_DATA fd = {0};
        HANDLE fHandle = FindFirstFile(search, &fd);
        while(INVALID_HANDLE_VALUE != fHandle)
        {
            if(FILE_ATTRIBUTE_DIRECTORY == (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) //only check directories
            {
                if(0 != (fd.dwFileAttributes & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN))) //only check hidden and/or system directories
                {
                    //the recycle bin directory itself won't be marked, but a SID-specific child directory will, so now look at them
                    CString childSearch;
                    childSearch.Format(L"%c:\\%s\\*", path[0], fd.cFileName);
                    WIN32_FIND_DATA childFD = {0};
                    HANDLE childHandle = FindFirstFile(childSearch, &childFD);
                    while(INVALID_HANDLE_VALUE != childHandle)
                    {
                        if((FILE_ATTRIBUTE_DIRECTORY == (childFD.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) && //only check directories
                            (childFD.cFileName[0] != L'.')) //don't check . and .. dirs
                        {
                            CString fullPath;
                            fullPath.Format(L"%c:\\%s\\%s", path[0], fd.cFileName, childFD.cFileName);
                            CLSID id = {0};
                            HRESULT hr = GetFolderCLSID(fullPath, id);
                            if(SUCCEEDED(hr))
                            {
                                if(IsEqualGUID(CLSID_RecycleBin, id))
                                {
                                    FindClose(childHandle);
                                    FindClose(fHandle);
                                    //return the parent (recycle bin) directory
                                    fullPath.Format(L"%c:\\%s", path[0], fd.cFileName);
                                    return fullPath;
                                }
                            }
                            else
                            {
                                Log(logERROR, L"GetFolderCLSID returned %08X for %s", hr, fullPath);
                            }
                        }
    
                        if(FALSE == FindNextFile(childHandle, &childFD))
                        {
                            FindClose(childHandle);
                            childHandle = INVALID_HANDLE_VALUE;
                        }
                    }
                }
            }
            if(FALSE == FindNextFile(fHandle, &fd))
            {
                FindClose(fHandle);
                fHandle = INVALID_HANDLE_VALUE;
            }
        }
        _ASSERT(0);
        return L"";
    }
    
    
    //Works on Windows 2000, and even as Local System account
    HRESULT GetFolderCLSID(LPCWSTR path, CLSID& pathCLSID)
    {
        LPMALLOC pMalloc = NULL;
        HRESULT hr = 0;
        if (SUCCEEDED(hr = SHGetMalloc(&pMalloc))) 
        {
            LPSHELLFOLDER pshfDesktop = NULL;
            if (SUCCEEDED(hr = SHGetDesktopFolder(&pshfDesktop))) 
            {
                LPITEMIDLIST pidl = NULL;
                DWORD dwAttributes = SFGAO_FOLDER;
                if (SUCCEEDED(hr = pshfDesktop->ParseDisplayName(NULL, NULL, (LPWSTR)path, NULL, &pidl, &dwAttributes))) 
                {
                    LPPERSIST pPersist = NULL;
                    if (SUCCEEDED(hr = pshfDesktop->BindToObject(pidl, NULL, IID_IPersist, (LPVOID *) &pPersist))) 
                    {
                        hr = pPersist->GetClassID(&pathCLSID); 
                        pPersist->Release();
                    } 
                    pMalloc->Free(pidl);
                } 
                pshfDesktop->Release();
            } 
            pMalloc->Release();
        }
        return hr;
    }
    
    
    //Not supported on Windows 2000 since SHParseDisplayName wasn't implemented then
    //HRESULT GetFolderCLSID(LPCWSTR pszPath, CLSID& pathCLSID)
    //{
    //  SHDESCRIPTIONID did = {0};
    //  HRESULT hr = 0;
    //  LPITEMIDLIST pidl = NULL;
    //  if (SUCCEEDED(hr = SHParseDisplayName(pszPath, NULL, &pidl, 0, NULL))) //not supported by Windows 2000
    //  {
    //      IShellFolder *psf = NULL;
    //      LPCITEMIDLIST pidlChild = NULL;
    //      if (SUCCEEDED(hr = SHBindToParent(pidl, IID_IShellFolder, (void**)&psf, &pidlChild))) 
    //      {
    //          hr = SHGetDataFromIDList(psf, pidlChild, SHGDFIL_DESCRIPTIONID, &did, sizeof(did));
    //          psf->Release();
    //          pathCLSID = did.clsid;
    //      }
    //      CoTaskMemFree(pidl);
    //  }
    //  return hr;
    //}
    

提交回复
热议问题