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

Last change on this file since 130 was 130, checked in by jrpelegrina, 3 years ago

First release to xenial

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