[vlc-commits] smb: Fix samba browsing on windows
Hugo Beauzée-Luyssen
git at videolan.org
Tue Nov 7 14:25:13 CET 2017
vlc | branch: master | Hugo Beauzée-Luyssen <hugo at beauzee.fr> | Tue Nov 7 11:00:48 2017 +0100| [b838ea1c0948dc07ca3ff51972dc3c4f7f42fbbd] | committer: Hugo Beauzée-Luyssen
smb: Fix samba browsing on windows
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=b838ea1c0948dc07ca3ff51972dc3c4f7f42fbbd
---
modules/access/Makefile.am | 2 +-
modules/access/smb.c | 85 ++++++++++++++++++++++++++++++++++++++++------
2 files changed, 75 insertions(+), 12 deletions(-)
diff --git a/modules/access/Makefile.am b/modules/access/Makefile.am
index 51ac1157c5..d193b27935 100644
--- a/modules/access/Makefile.am
+++ b/modules/access/Makefile.am
@@ -344,7 +344,7 @@ libsmb_plugin_la_SOURCES = access/smb.c access/smb_common.h
libsmb_plugin_la_CFLAGS = $(AM_CFLAGS) $(SMBCLIENT_CFLAGS)
libsmb_plugin_la_LIBADD = $(SMBCLIENT_LIBS)
if HAVE_WIN32
-libsmb_plugin_la_LIBADD += -lmpr
+libsmb_plugin_la_LIBADD += -lmpr -lnetapi32
endif
libsmb_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(accessdir)'
access_LTLIBRARIES += $(LTLIBsmb)
diff --git a/modules/access/smb.c b/modules/access/smb.c
index 13d4e56118..2f792a63bc 100644
--- a/modules/access/smb.c
+++ b/modules/access/smb.c
@@ -34,6 +34,8 @@
# include <fcntl.h>
# include <sys/stat.h>
# include <io.h>
+# include <windows.h>
+# include <lm.h>
# define smbc_open(a,b,c) vlc_open(a,b,c)
# define smbc_stat(a,b) _stati64(a,b)
# define smbc_read read
@@ -50,6 +52,7 @@
#include <vlc_input_item.h>
#include <vlc_url.h>
#include <vlc_keystore.h>
+#include <vlc_charset.h>
#include "smb_common.h"
@@ -83,9 +86,7 @@ vlc_module_end ()
static ssize_t Read( stream_t *, void *, size_t );
static int Seek( stream_t *, uint64_t );
static int Control( stream_t *, int, va_list );
-#ifndef _WIN32
static int DirRead( stream_t *, input_item_node_t * );
-#endif
struct access_sys_t
{
@@ -235,16 +236,12 @@ static int Open( vlc_object_t *p_this )
if( b_is_dir )
{
-#ifdef _WIN32
- free( psz_uri );
- vlc_UrlClean( &url );
- return VLC_EGENERIC;
-#else
p_sys->url = url;
p_access->pf_readdir = DirRead;
p_access->pf_control = access_vaDirectoryControlHelper;
- i_smb = smbc_opendir( psz_uri );
i_size = 0;
+#ifndef _WIN32
+ i_smb = smbc_opendir( psz_uri );
if( i_smb < 0 )
vlc_UrlClean( &p_sys->url );
#endif
@@ -258,12 +255,14 @@ static int Open( vlc_object_t *p_this )
}
free( psz_uri );
+#ifndef _WIN32
if( i_smb < 0 )
{
msg_Err( p_access, "open failed for '%s' (%s)",
p_access->psz_location, vlc_strerror_c(errno) );
return VLC_EGENERIC;
}
+#endif
p_sys->size = i_size;
p_sys->i_smb = i_smb;
@@ -330,19 +329,20 @@ static ssize_t Read( stream_t *p_access, void *p_buffer, size_t i_len )
return i_read;
}
-#ifndef _WIN32
/*****************************************************************************
* DirRead:
*****************************************************************************/
static int DirRead (stream_t *p_access, input_item_node_t *p_node )
{
access_sys_t *p_sys = p_access->p_sys;
- struct smbc_dirent *p_entry;
int i_ret = VLC_SUCCESS;
struct vlc_readdir_helper rdh;
vlc_readdir_helper_init( &rdh, p_access, p_node );
+#ifndef _WIN32
+ struct smbc_dirent *p_entry;
+
while( i_ret == VLC_SUCCESS && ( p_entry = smbc_readdir( p_sys->i_smb ) ) )
{
char *psz_uri;
@@ -392,12 +392,75 @@ static int DirRead (stream_t *p_access, input_item_node_t *p_node )
i_type, ITEM_NET );
free( psz_uri );
}
+#else
+ // Handle share listing from here. Directory browsing is handled by the
+ // usual filesystem module.
+ SHARE_INFO_1 *p_info;
+ DWORD i_share_enum_res;
+ DWORD i_nb_elem;
+ DWORD i_resume_handle = 0;
+ DWORD i_total_elements; // Unused, but needs to be passed
+ wchar_t *wpsz_host = ToWide( p_sys->url.psz_host );
+ if( wpsz_host == NULL )
+ return VLC_ENOMEM;
+ do
+ {
+ i_share_enum_res = NetShareEnum( wpsz_host, 1, (LPBYTE*)&p_info,
+ MAX_PREFERRED_LENGTH, &i_nb_elem,
+ &i_total_elements, &i_resume_handle );
+ if( i_share_enum_res == ERROR_SUCCESS ||
+ i_share_enum_res == ERROR_MORE_DATA )
+ {
+ for ( DWORD i = 0; i < i_nb_elem; ++i )
+ {
+ SHARE_INFO_1 *p_current = p_info + i;
+ if( p_current->shi1_type & STYPE_SPECIAL )
+ continue;
+ char* psz_name = FromWide( p_current->shi1_netname );
+ if( psz_name == NULL )
+ {
+ i_ret = VLC_ENOMEM;
+ break;
+ }
+
+ char* psz_path;
+ if( smb_get_uri( p_access, &psz_path, NULL, NULL, NULL,
+ p_sys->url.psz_host, p_sys->url.psz_path,
+ psz_name ) < 0 )
+ {
+ free( psz_name );
+ i_ret = VLC_ENOMEM;
+ break;
+ }
+ free( psz_name );
+ // We need to concatenate the scheme before, as the window version
+ // of smb_get_uri generates a path (and the other call site needs
+ // a path). The path is already prefixed by "//" so we just need
+ // to add "file:"
+ char* psz_uri;
+ if( asprintf( &psz_uri, "file:%s", psz_path ) < 0 )
+ {
+ free( psz_path );
+ i_ret = VLC_ENOMEM;
+ break;
+ }
+ free( psz_path );
+
+ i_ret = vlc_readdir_helper_additem( &rdh, psz_uri, NULL,
+ psz_name, ITEM_TYPE_DIRECTORY, ITEM_NET );
+ free( psz_uri );
+ }
+ }
+ NetApiBufferFree( p_info );
+ } while( i_share_enum_res == ERROR_MORE_DATA && i_ret == VLC_SUCCESS );
+
+ free( wpsz_host );
+#endif
vlc_readdir_helper_finish( &rdh, i_ret == VLC_SUCCESS );
return i_ret;
}
-#endif
/*****************************************************************************
* Control:
More information about the vlc-commits
mailing list