source: filezilla/trunk/fuentes/src/interface/volume_enumerator.cpp @ 3185

Last change on this file since 3185 was 3185, checked in by jrpelegrina, 2 years ago

Update new version: 3.15.02

File size: 4.8 KB
Line 
1#include <filezilla.h>
2#include "volume_enumerator.h"
3
4#ifdef __WXMSW__
5
6#include <wx/msw/registry.h>
7
8DEFINE_EVENT_TYPE(fzEVT_VOLUMEENUMERATED)
9DEFINE_EVENT_TYPE(fzEVT_VOLUMESENUMERATED)
10
11CVolumeDescriptionEnumeratorThread::CVolumeDescriptionEnumeratorThread(wxEvtHandler* pEvtHandler)
12        : m_pEvtHandler(pEvtHandler)
13{
14        m_failure = false;
15        m_stop = false;
16        m_running = true;
17
18        if (!run()) {
19                m_running = false;
20                m_failure = true;
21        }
22}
23
24CVolumeDescriptionEnumeratorThread::~CVolumeDescriptionEnumeratorThread()
25{
26        m_stop = true;
27        join();
28
29        for (auto iter = m_volumeInfo.cbegin(); iter != m_volumeInfo.cend(); ++iter) {
30                delete [] iter->pVolume;
31                delete [] iter->pVolumeName;
32        }
33        m_volumeInfo.clear();
34}
35
36void CVolumeDescriptionEnumeratorThread::entry()
37{
38        if (!GetDriveLabels())
39                m_failure = true;
40
41        m_running = false;
42
43        m_pEvtHandler->QueueEvent(new wxCommandEvent(fzEVT_VOLUMESENUMERATED));
44}
45
46void CVolumeDescriptionEnumeratorThread::ProcessDrive(wxString const& drive)
47{
48        if ( GetDriveLabel(drive)) {
49                m_pEvtHandler->QueueEvent(new wxCommandEvent(fzEVT_VOLUMEENUMERATED));
50        }
51}
52
53bool CVolumeDescriptionEnumeratorThread::GetDriveLabel(wxString const& drive)
54{
55        int len = drive.size();
56        wxChar* pVolume = new wxChar[drive.size() + 1];
57        wxStrcpy(pVolume, drive);
58        if (pVolume[drive.size() - 1] == '\\') {
59                pVolume[drive.size() - 1] = 0;
60                --len;
61        }
62        if (!*pVolume) {
63                delete [] pVolume;
64                return false;
65        }
66
67        // Check if it is a network share
68        wxChar *share_name = new wxChar[512];
69        DWORD dwSize = 511;
70        if (!WNetGetConnection(pVolume, share_name, &dwSize)) {
71                fz::scoped_lock l(sync_);
72                t_VolumeInfoInternal volumeInfo;
73                volumeInfo.pVolume = pVolume;
74                volumeInfo.pVolumeName = share_name;
75                m_volumeInfo.push_back(volumeInfo);
76                return true;
77        }
78        else
79                delete [] share_name;
80
81        // Get the label of the drive
82        wxChar* pVolumeName = new wxChar[501];
83        int oldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
84        BOOL res = GetVolumeInformation(drive.wc_str(), pVolumeName, 500, 0, 0, 0, 0, 0);
85        SetErrorMode(oldErrorMode);
86        if (res && pVolumeName[0]) {
87                fz::scoped_lock l(sync_);
88                t_VolumeInfoInternal volumeInfo;
89                volumeInfo.pVolume = pVolume;
90                volumeInfo.pVolumeName = pVolumeName;
91                m_volumeInfo.push_back(volumeInfo);
92                return true;
93        }
94
95        delete [] pVolumeName;
96        delete [] pVolume;
97
98        return false;
99}
100
101bool CVolumeDescriptionEnumeratorThread::GetDriveLabels()
102{
103        std::list<wxString> drives = GetDrives();
104
105        if( drives.empty() ) {
106                return true;
107        }
108
109        std::list<wxString>::const_iterator drive_a = drives.end();
110        for( std::list<wxString>::const_iterator it = drives.begin(); it != drives.end() && !m_stop; ++it ) {
111                if (m_stop) {
112                        return false;
113                }
114
115                wxString const& drive = *it;
116                if( (drive[0] == 'a' || drive[0] == 'A') && drive_a == drives.end() ) {
117                        // Defer processing of A:, most commonly the slowest of all drives.
118                        drive_a = it;
119                }
120                else {
121                        ProcessDrive(drive);
122                }
123        }
124
125        if( drive_a != drives.end() && !m_stop ) {
126                ProcessDrive(*drive_a);
127        }
128
129        return !m_stop;
130}
131
132long CVolumeDescriptionEnumeratorThread::GetDrivesToHide()
133{
134        long drivesToHide = 0;
135        // Adhere to the NODRIVES group policy
136        wxRegKey key(_T("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"));
137        if (key.Exists()) {
138                wxLogNull null; // QueryValue can fail if item has wrong type
139                if (!key.HasValue(_T("NoDrives")) || !key.QueryValue(_T("NoDrives"), &drivesToHide))
140                        drivesToHide = 0;
141        }
142        return drivesToHide;
143}
144
145bool CVolumeDescriptionEnumeratorThread::IsHidden(wxChar const* drive, long noDrives)
146{
147        int bit = 0;
148        if (drive && drive[0] != 0 && drive[1] == ':') {
149                wxChar letter = drive[0];
150                if (letter >= 'A' && letter <= 'Z')
151                        bit = 1 << (letter - 'A');
152                else if (letter >= 'a' && letter <= 'z')
153                        bit = 1 << (letter - 'a');
154        }
155
156        return (noDrives & bit) != 0;
157}
158
159std::list<wxString> CVolumeDescriptionEnumeratorThread::GetDrives()
160{
161        std::list<wxString> ret;
162
163        long drivesToHide = GetDrivesToHide();
164
165        DWORD bufferLen{};
166        wxChar* drives{};
167
168        DWORD neededLen = 1000;
169
170        do {
171                delete[] drives;
172
173                bufferLen = neededLen * 2;
174                drives = new wxChar[bufferLen + 1];
175                neededLen = GetLogicalDriveStrings(bufferLen, drives);
176        } while (neededLen >= bufferLen);
177        drives[neededLen] = 0;
178
179
180        const wxChar* pDrive = drives;
181        while (*pDrive) {
182                const int drivelen = fz::strlen(pDrive);
183
184                if (!IsHidden(pDrive, drivesToHide)) {
185                        ret.push_back(pDrive);
186                }
187
188                pDrive += drivelen + 1;
189        }
190       
191        delete [] drives;
192
193        return ret;
194}
195
196
197std::list<CVolumeDescriptionEnumeratorThread::t_VolumeInfo> CVolumeDescriptionEnumeratorThread::GetVolumes()
198{
199        std::list<t_VolumeInfo> volumeInfo;
200
201        fz::scoped_lock l(sync_);
202
203        for (auto const& internal_info : m_volumeInfo) {
204                t_VolumeInfo info;
205                info.volume = internal_info.pVolume;
206                delete[] internal_info.pVolume;
207                info.volumeName = internal_info.pVolumeName;
208                delete[] internal_info.pVolumeName;
209                volumeInfo.push_back(info);
210        }
211        m_volumeInfo.clear();
212
213        return volumeInfo;
214}
215
216#endif //__WXMSW__
Note: See TracBrowser for help on using the repository browser.