]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/volume.cpp
Fix assert when creating wxBitmapButton without a valid bitmap in wxMSW.
[wxWidgets.git] / src / msw / volume.cpp
index 97723420c3dd333622161c5b102004e07ca201cd..3ea20ccae4a7c4083df78632a96d5acf68ca5c5f 100644 (file)
 // headers
 // ----------------------------------------------------------------------------
 
 // headers
 // ----------------------------------------------------------------------------
 
-#ifdef __GNUG__
-    #pragma implementation "fsvolume.h"
-#endif
-
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
 
 #if wxUSE_FSVOLUME
 
 
 #if wxUSE_FSVOLUME
 
+#include "wx/volume.h"
+
 #ifndef WX_PRECOMP
     #if wxUSE_GUI
         #include "wx/icon.h"
     #endif
     #include "wx/intl.h"
 #ifndef WX_PRECOMP
     #if wxUSE_GUI
         #include "wx/icon.h"
     #endif
     #include "wx/intl.h"
+    #include "wx/log.h"
+    #include "wx/hashmap.h"
+    #include "wx/filefn.h"
 #endif // WX_PRECOMP
 
 #include "wx/dir.h"
 #endif // WX_PRECOMP
 
 #include "wx/dir.h"
-#include "wx/hashmap.h"
 #include "wx/dynlib.h"
 #include "wx/arrimpl.cpp"
 
 #include "wx/dynlib.h"
 #include "wx/arrimpl.cpp"
 
-#include "wx/volume.h"
-
+// some compilers require including <windows.h> before <shellapi.h> so do it
+// even if this is not necessary with most of them
+#include "wx/msw/wrapwin.h"
 #include <shellapi.h>
 #include <shellapi.h>
+#include <shlobj.h>
 #include "wx/msw/missing.h"
 
 #if wxUSE_BASE
 #include "wx/msw/missing.h"
 
 #if wxUSE_BASE
@@ -52,7 +54,9 @@
 // Dynamic library function defs.
 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 // Dynamic library function defs.
 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
+#if wxUSE_DYNLIB_CLASS
 static wxDynamicLibrary s_mprLib;
 static wxDynamicLibrary s_mprLib;
+#endif
 
 typedef DWORD (WINAPI* WNetOpenEnumPtr)(DWORD, DWORD, DWORD, LPNETRESOURCE, LPHANDLE);
 typedef DWORD (WINAPI* WNetEnumResourcePtr)(HANDLE, LPDWORD, LPVOID, LPDWORD);
 
 typedef DWORD (WINAPI* WNetOpenEnumPtr)(DWORD, DWORD, DWORD, LPNETRESOURCE, LPHANDLE);
 typedef DWORD (WINAPI* WNetEnumResourcePtr)(HANDLE, LPDWORD, LPVOID, LPDWORD);
@@ -146,17 +150,19 @@ static unsigned GetBasicFlags(const wxChar* filename)
     }
 
     //-----------------------------------------------------------------------
     }
 
     //-----------------------------------------------------------------------
-    // The following will most likely will not modify anything not set above,
+    // The following most likely will not modify anything not set above,
     // and will not work at all for network shares or empty CD ROM drives.
     // But it is a good check if the Win API ever gets better about reporting
     // this information.
     //-----------------------------------------------------------------------
     SHFILEINFO fi;
     // and will not work at all for network shares or empty CD ROM drives.
     // But it is a good check if the Win API ever gets better about reporting
     // this information.
     //-----------------------------------------------------------------------
     SHFILEINFO fi;
-    long rc;
-    rc = SHGetFileInfo(filename, 0, &fi, sizeof(fi), SHGFI_ATTRIBUTES );
+    long rc = SHGetFileInfo(filename, 0, &fi, sizeof(fi), SHGFI_ATTRIBUTES);
     if (!rc)
     {
     if (!rc)
     {
-        wxLogError(_("Cannot read typename from '%s'!"), filename);
+        // this error is not fatal, so don't show a message to the user about
+        // it, otherwise it would appear every time a generic directory picker
+        // dialog is used and there is a connected network drive
+        wxLogLastError(wxT("SHGetFileInfo"));
     }
     else
     {
     }
     else
     {
@@ -179,28 +185,28 @@ static unsigned GetBasicFlags(const wxChar* filename)
 // Purpose: Add a file to the list if it meets the filter requirement.
 // Notes: - See GetBasicFlags for remarks about the Mounted flag.
 //=============================================================================
 // Purpose: Add a file to the list if it meets the filter requirement.
 // Notes: - See GetBasicFlags for remarks about the Mounted flag.
 //=============================================================================
-static bool FilteredAdd(wxArrayString& list, const wxChar* filename, 
+static bool FilteredAdd(wxArrayString& list, const wxChar* filename,
                         unsigned flagsSet, unsigned flagsUnset)
 {
                         unsigned flagsSet, unsigned flagsUnset)
 {
-    bool accept = TRUE;
+    bool accept = true;
     unsigned flags = GetBasicFlags(filename);
 
     if (flagsSet & wxFS_VOL_MOUNTED && !(flags & wxFS_VOL_MOUNTED))
     unsigned flags = GetBasicFlags(filename);
 
     if (flagsSet & wxFS_VOL_MOUNTED && !(flags & wxFS_VOL_MOUNTED))
-        accept = FALSE;
+        accept = false;
     else if (flagsUnset & wxFS_VOL_MOUNTED && (flags & wxFS_VOL_MOUNTED))
     else if (flagsUnset & wxFS_VOL_MOUNTED && (flags & wxFS_VOL_MOUNTED))
-        accept = FALSE;
+        accept = false;
     else if (flagsSet & wxFS_VOL_REMOVABLE && !(flags & wxFS_VOL_REMOVABLE))
     else if (flagsSet & wxFS_VOL_REMOVABLE && !(flags & wxFS_VOL_REMOVABLE))
-        accept = FALSE;
+        accept = false;
     else if (flagsUnset & wxFS_VOL_REMOVABLE && (flags & wxFS_VOL_REMOVABLE))
     else if (flagsUnset & wxFS_VOL_REMOVABLE && (flags & wxFS_VOL_REMOVABLE))
-        accept = FALSE;
+        accept = false;
     else if (flagsSet & wxFS_VOL_READONLY && !(flags & wxFS_VOL_READONLY))
     else if (flagsSet & wxFS_VOL_READONLY && !(flags & wxFS_VOL_READONLY))
-        accept = FALSE;
+        accept = false;
     else if (flagsUnset & wxFS_VOL_READONLY && (flags & wxFS_VOL_READONLY))
     else if (flagsUnset & wxFS_VOL_READONLY && (flags & wxFS_VOL_READONLY))
-        accept = FALSE;
+        accept = false;
     else if (flagsSet & wxFS_VOL_REMOTE && !(flags & wxFS_VOL_REMOTE))
     else if (flagsSet & wxFS_VOL_REMOTE && !(flags & wxFS_VOL_REMOTE))
-        accept = FALSE;
+        accept = false;
     else if (flagsUnset & wxFS_VOL_REMOTE && (flags & wxFS_VOL_REMOTE))
     else if (flagsUnset & wxFS_VOL_REMOTE && (flags & wxFS_VOL_REMOTE))
-        accept = FALSE;
+        accept = false;
 
     // Add to the list if passed the filter.
     if (accept)
 
     // Add to the list if passed the filter.
     if (accept)
@@ -216,7 +222,7 @@ static bool FilteredAdd(wxArrayString& list, const wxChar* filename,
 //          all items while determining which are connected and not.  So this
 //          function will find either all items or connected items.
 //=============================================================================
 //          all items while determining which are connected and not.  So this
 //          function will find either all items or connected items.
 //=============================================================================
-static void BuildListFromNN(wxArrayString& list, NETRESOURCE* pResSrc, 
+static void BuildListFromNN(wxArrayString& list, NETRESOURCE* pResSrc,
                             unsigned flagsSet, unsigned flagsUnset)
 {
     HANDLE hEnum;
                             unsigned flagsSet, unsigned flagsUnset)
 {
     HANDLE hEnum;
@@ -263,7 +269,18 @@ static void BuildListFromNN(wxArrayString& list, NETRESOURCE* pResSrc,
                 {
                     wxString filename(pRes->lpRemoteName);
 
                 {
                     wxString filename(pRes->lpRemoteName);
 
-                    if (filename.Len())
+                    // if the drive is unavailable, FilteredAdd() can hang for
+                    // a long time and, moreover, its failure appears to be not
+                    // cached so this will happen every time we use it, so try
+                    // a much quicker wxDirExists() test (which still hangs but
+                    // for much shorter time) for locally mapped drives first
+                    // to try to avoid this
+                    if ( pRes->lpLocalName &&
+                            *pRes->lpLocalName &&
+                                !wxDirExists(pRes->lpLocalName) )
+                        continue;
+
+                    if (!filename.empty())
                     {
                         if (filename.Last() != '\\')
                             filename.Append('\\');
                     {
                         if (filename.Last() != '\\')
                             filename.Append('\\');
@@ -271,7 +288,7 @@ static void BuildListFromNN(wxArrayString& list, NETRESOURCE* pResSrc,
                         // The filter function will not know mounted from unmounted, and neither do we unless
                         // we are iterating using RESOURCE_CONNECTED, in which case they all are mounted.
                         // Volumes on disconnected servers, however, will correctly show as unmounted.
                         // The filter function will not know mounted from unmounted, and neither do we unless
                         // we are iterating using RESOURCE_CONNECTED, in which case they all are mounted.
                         // Volumes on disconnected servers, however, will correctly show as unmounted.
-                        FilteredAdd(list, filename, flagsSet, flagsUnset&~wxFS_VOL_MOUNTED);
+                        FilteredAdd(list, filename.wx_str(), flagsSet, flagsUnset&~wxFS_VOL_MOUNTED);
                         if (scope == RESOURCE_GLOBALNET)
                             s_fileInfo[filename].m_flags &= ~wxFS_VOL_MOUNTED;
                     }
                         if (scope == RESOURCE_GLOBALNET)
                             s_fileInfo[filename].m_flags &= ~wxFS_VOL_MOUNTED;
                     }
@@ -289,9 +306,9 @@ static void BuildListFromNN(wxArrayString& list, NETRESOURCE* pResSrc,
 // Function: CompareFcn
 // Purpose: Used to sort the NN list alphabetically, case insensitive.
 //=============================================================================
 // Function: CompareFcn
 // Purpose: Used to sort the NN list alphabetically, case insensitive.
 //=============================================================================
-static int CompareFcn(wxString* first, wxString* second)
+static int CompareFcn(const wxString& first, const wxString& second)
 {
 {
-    return wxStricmp(first->c_str(), second->c_str());
+    return wxStricmp(first.c_str(), second.c_str());
 } // CompareFcn
 
 //=============================================================================
 } // CompareFcn
 
 //=============================================================================
@@ -302,19 +319,19 @@ static int CompareFcn(wxString* first, wxString* second)
 //          way manually.
 //        - The resulting list is sorted alphabetically.
 //=============================================================================
 //          way manually.
 //        - The resulting list is sorted alphabetically.
 //=============================================================================
-static bool BuildRemoteList(wxArrayString& list, NETRESOURCE* pResSrc, 
+static bool BuildRemoteList(wxArrayString& list, NETRESOURCE* pResSrc,
                             unsigned flagsSet, unsigned flagsUnset)
 {
     // NN query depends on dynamically loaded library.
     if (!s_pWNetOpenEnum || !s_pWNetEnumResource || !s_pWNetCloseEnum)
     {
         wxLogError(_("Failed to load mpr.dll."));
                             unsigned flagsSet, unsigned flagsUnset)
 {
     // NN query depends on dynamically loaded library.
     if (!s_pWNetOpenEnum || !s_pWNetEnumResource || !s_pWNetCloseEnum)
     {
         wxLogError(_("Failed to load mpr.dll."));
-        return FALSE;
+        return false;
     }
 
     // Don't waste time doing the work if the flags conflict.
     if (flagsSet & wxFS_VOL_MOUNTED && flagsUnset & wxFS_VOL_MOUNTED)
     }
 
     // Don't waste time doing the work if the flags conflict.
     if (flagsSet & wxFS_VOL_MOUNTED && flagsUnset & wxFS_VOL_MOUNTED)
-        return FALSE;
+        return false;
 
     //----------------------------------------------
     // Generate the list according to the flags set.
 
     //----------------------------------------------
     // Generate the list according to the flags set.
@@ -335,15 +352,14 @@ static bool BuildRemoteList(wxArrayString& list, NETRESOURCE* pResSrc,
         mounted.Sort(CompareFcn);
 
         // apply list from bottom to top to preserve indexes if removing items.
         mounted.Sort(CompareFcn);
 
         // apply list from bottom to top to preserve indexes if removing items.
-        int iList = list.GetCount()-1;
-        int iMounted;
-        for (iMounted = mounted.GetCount()-1; iMounted >= 0 && iList >= 0; iMounted--)
+        ssize_t iList = list.GetCount()-1;
+        for (ssize_t iMounted = mounted.GetCount()-1; iMounted >= 0 && iList >= 0; iMounted--)
         {
             int compare;
             wxString all(list[iList]);
             wxString mount(mounted[iMounted]);
 
         {
             int compare;
             wxString all(list[iList]);
             wxString mount(mounted[iMounted]);
 
-            while (compare = 
+            while (compare =
                      wxStricmp(list[iList].c_str(), mounted[iMounted].c_str()),
                    compare > 0 && iList >= 0)
             {
                      wxStricmp(list[iList].c_str(), mounted[iMounted].c_str()),
                    compare > 0 && iList >= 0)
             {
@@ -366,7 +382,7 @@ static bool BuildRemoteList(wxArrayString& list, NETRESOURCE* pResSrc,
         }
     }
 
         }
     }
 
-    return TRUE;
+    return true;
 } // BuildRemoteList
 
 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 } // BuildRemoteList
 
 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -380,19 +396,21 @@ static bool BuildRemoteList(wxArrayString& list, NETRESOURCE* pResSrc,
 //=============================================================================
 wxArrayString wxFSVolumeBase::GetVolumes(int flagsSet, int flagsUnset)
 {
 //=============================================================================
 wxArrayString wxFSVolumeBase::GetVolumes(int flagsSet, int flagsUnset)
 {
-    InterlockedExchange(&s_cancelSearch, FALSE);     // reset
+    ::InterlockedExchange(&s_cancelSearch, FALSE);     // reset
 
 
-    if (!s_mprLib.IsLoaded() && s_mprLib.Load(_T("mpr.dll")))
+#if wxUSE_DYNLIB_CLASS
+    if (!s_mprLib.IsLoaded() && s_mprLib.Load(wxT("mpr.dll")))
     {
 #ifdef UNICODE
     {
 #ifdef UNICODE
-        s_pWNetOpenEnum = (WNetOpenEnumPtr)s_mprLib.GetSymbol(_T("WNetOpenEnumW"));
-        s_pWNetEnumResource = (WNetEnumResourcePtr)s_mprLib.GetSymbol(_T("WNetEnumResourceW"));
+        s_pWNetOpenEnum = (WNetOpenEnumPtr)s_mprLib.GetSymbol(wxT("WNetOpenEnumW"));
+        s_pWNetEnumResource = (WNetEnumResourcePtr)s_mprLib.GetSymbol(wxT("WNetEnumResourceW"));
 #else
 #else
-        s_pWNetOpenEnum = (WNetOpenEnumPtr)s_mprLib.GetSymbol(_T("WNetOpenEnumA"));
-        s_pWNetEnumResource = (WNetEnumResourcePtr)s_mprLib.GetSymbol(_T("WNetEnumResourceA"));
+        s_pWNetOpenEnum = (WNetOpenEnumPtr)s_mprLib.GetSymbol(wxT("WNetOpenEnumA"));
+        s_pWNetEnumResource = (WNetEnumResourcePtr)s_mprLib.GetSymbol(wxT("WNetEnumResourceA"));
 #endif
 #endif
-        s_pWNetCloseEnum = (WNetCloseEnumPtr)s_mprLib.GetSymbol(_T("WNetCloseEnum"));
+        s_pWNetCloseEnum = (WNetCloseEnumPtr)s_mprLib.GetSymbol(wxT("WNetCloseEnum"));
     }
     }
+#endif
 
     wxArrayString list;
 
 
     wxArrayString list;
 
@@ -400,11 +418,11 @@ wxArrayString wxFSVolumeBase::GetVolumes(int flagsSet, int flagsUnset)
     // Local and mapped drives first.
     //-------------------------------
     // Allocate the required space for the API call.
     // Local and mapped drives first.
     //-------------------------------
     // Allocate the required space for the API call.
-    size_t chars = GetLogicalDriveStrings(0, 0);
+    const DWORD chars = GetLogicalDriveStrings(0, NULL);
     TCHAR* buf = new TCHAR[chars+1];
 
     // Get the list of drives.
     TCHAR* buf = new TCHAR[chars+1];
 
     // Get the list of drives.
-    chars = GetLogicalDriveStrings(chars, buf);
+    GetLogicalDriveStrings(chars, buf);
 
     // Parse the list into an array, applying appropriate filters.
     TCHAR *pVol;
 
     // Parse the list into an array, applying appropriate filters.
     TCHAR *pVol;
@@ -449,7 +467,7 @@ wxArrayString wxFSVolumeBase::GetVolumes(int flagsSet, int flagsUnset)
 //=============================================================================
 void wxFSVolumeBase::CancelSearch()
 {
 //=============================================================================
 void wxFSVolumeBase::CancelSearch()
 {
-    InterlockedExchange(&s_cancelSearch, TRUE);
+    ::InterlockedExchange(&s_cancelSearch, TRUE);
 } // CancelSearch
 
 //=============================================================================
 } // CancelSearch
 
 //=============================================================================
@@ -458,7 +476,7 @@ void wxFSVolumeBase::CancelSearch()
 //=============================================================================
 wxFSVolumeBase::wxFSVolumeBase()
 {
 //=============================================================================
 wxFSVolumeBase::wxFSVolumeBase()
 {
-    m_isOk = FALSE;
+    m_isOk = false;
 } // wxVolume
 
 //=============================================================================
 } // wxVolume
 
 //=============================================================================
@@ -477,14 +495,14 @@ wxFSVolumeBase::wxFSVolumeBase(const wxString& name)
 bool wxFSVolumeBase::Create(const wxString& name)
 {
     // assume fail.
 bool wxFSVolumeBase::Create(const wxString& name)
 {
     // assume fail.
-    m_isOk = FALSE;
+    m_isOk = false;
 
     // supplied.
     m_volName = name;
 
     // Display name.
     SHFILEINFO fi;
 
     // supplied.
     m_volName = name;
 
     // Display name.
     SHFILEINFO fi;
-    long rc = SHGetFileInfo(m_volName, 0, &fi, sizeof(fi), SHGFI_DISPLAYNAME);
+    long rc = SHGetFileInfo(m_volName.wx_str(), 0, &fi, sizeof(fi), SHGFI_DISPLAYNAME);
     if (!rc)
     {
         wxLogError(_("Cannot read typename from '%s'!"), m_volName.c_str());
     if (!rc)
     {
         wxLogError(_("Cannot read typename from '%s'!"), m_volName.c_str());
@@ -493,12 +511,12 @@ bool wxFSVolumeBase::Create(const wxString& name)
     m_dispName = fi.szDisplayName;
 
     // all tests passed.
     m_dispName = fi.szDisplayName;
 
     // all tests passed.
-    return m_isOk = TRUE;
+    return m_isOk = true;
 } // Create
 
 //=============================================================================
 // Function: IsOk
 } // Create
 
 //=============================================================================
 // Function: IsOk
-// Purpose: returns TRUE if the volume is legal.
+// Purpose: returns true if the volume is legal.
 // Notes: For fixed disks, it must exist.  For removable disks, it must also
 //        be present.  For Network Shares, it must also be logged in, etc.
 //=============================================================================
 // Notes: For fixed disks, it must exist.  For removable disks, it must also
 //        be present.  For Network Shares, it must also be logged in, etc.
 //=============================================================================
@@ -564,7 +582,7 @@ void wxFSVolume::InitIcons()
 wxIcon wxFSVolume::GetIcon(wxFSIconType type) const
 {
     wxCHECK_MSG( type >= 0 && (size_t)type < m_icons.GetCount(), wxNullIcon,
 wxIcon wxFSVolume::GetIcon(wxFSIconType type) const
 {
     wxCHECK_MSG( type >= 0 && (size_t)type < m_icons.GetCount(), wxNullIcon,
-                 _T("wxFSIconType::GetIcon(): invalid icon index") );
+                 wxT("wxFSIconType::GetIcon(): invalid icon index") );
 
     // Load on demand.
     if (m_icons[type].IsNull())
 
     // Load on demand.
     if (m_icons[type].IsNull())
@@ -587,17 +605,19 @@ wxIcon wxFSVolume::GetIcon(wxFSIconType type) const
         case wxFS_VOL_ICO_SEL_LARGE:
             flags |= SHGFI_SHELLICONSIZE | SHGFI_OPENICON;
             break;
         case wxFS_VOL_ICO_SEL_LARGE:
             flags |= SHGFI_SHELLICONSIZE | SHGFI_OPENICON;
             break;
-            
+
         case wxFS_VOL_ICO_MAX:
         case wxFS_VOL_ICO_MAX:
-            wxFAIL_MSG(_T("wxFS_VOL_ICO_MAX is not valid icon type"));
+            wxFAIL_MSG(wxT("wxFS_VOL_ICO_MAX is not valid icon type"));
             break;
         }
 
         SHFILEINFO fi;
             break;
         }
 
         SHFILEINFO fi;
-        long rc = SHGetFileInfo(m_volName, 0, &fi, sizeof(fi), flags);
+        long rc = SHGetFileInfo(m_volName.wx_str(), 0, &fi, sizeof(fi), flags);
         m_icons[type].SetHICON((WXHICON)fi.hIcon);
         if (!rc || !fi.hIcon)
         m_icons[type].SetHICON((WXHICON)fi.hIcon);
         if (!rc || !fi.hIcon)
+        {
             wxLogError(_("Cannot load icon from '%s'."), m_volName.c_str());
             wxLogError(_("Cannot load icon from '%s'."), m_volName.c_str());
+        }
     }
 
     return m_icons[type];
     }
 
     return m_icons[type];
@@ -606,4 +626,3 @@ wxIcon wxFSVolume::GetIcon(wxFSIconType type) const
 #endif // wxUSE_GUI
 
 #endif // wxUSE_FSVOLUME
 #endif // wxUSE_GUI
 
 #endif // wxUSE_FSVOLUME
-