[prev in list] [next in list] [prev in thread] [next in thread] 

List:       wine-devel
Subject:    <<PATCH>> Added shell32.dll functions to browse for unix directory;
From:       Robert van Herk <robert () robertvanherk ! nl>
Date:       2004-11-30 16:20:29
Message-ID: 41AC9DCD.9070404 () robertvanherk ! nl
[Download RAW message or body]

Changes:

Added functionality to browse for a UNIX folder.
This is done by making two new funtions in dlls/shell32/brsfolder.c, namely
        wine_shell_browse_for_UNIX_directoryA
        wine_shell_browse_for_UNIX_directoryW
These functions are exported in shlobj.h.

The original code that allowed just for picking a Windows folder, was 
split up.
It was to be found in brsfolder.c, but I split this in:
brsfolder.c
brsfolder.h
brsfolder_windows.c
brsfolder_windows.h
brsfolder_unix.c
brsfolder_unix.h
unixTools.c
unixTools.h,
Otherwise I found the code to be incomprehendible.

Furthermore, winecfg now uses the wine_shell_browse_for_UNIX_directoryA
to let the user pick a UNIX directory as root for his virtual drive 
mappings.

Regards,
Robert van Herk

["patch.diff" (text/x-patch)]

? dlls/shell32/brsfolder.h
? dlls/shell32/brsfolder_unix.c
? dlls/shell32/brsfolder_unix.h
? dlls/shell32/brsfolder_windows.c
? dlls/shell32/brsfolder_windows.h
? dlls/shell32/unixTools.c
? dlls/shell32/unixTools.h
Index: dlls/shell32/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/shell32/Makefile.in,v
retrieving revision 1.86
diff -u -r1.86 Makefile.in
--- dlls/shell32/Makefile.in	27 Oct 2004 00:47:53 -0000	1.86
+++ dlls/shell32/Makefile.in	30 Nov 2004 14:57:03 -0000
@@ -12,6 +12,8 @@
 	authors.c \
 	autocomplete.c \
 	brsfolder.c \
+	brsfolder_windows.c \
+	brsfolder_unix.c \
 	changenotify.c \
 	classes.c \
 	clipboard.c \
@@ -46,7 +48,8 @@
 	shpolicy.c \
 	shv_bg_cmenu.c \
 	shv_item_cmenu.c \
-	systray.c
+	systray.c \
+	unixTools.c
 
 RC_SRCS = shres.rc
 RC_BINSRC = shres.rc
Index: dlls/shell32/brsfolder.c
===================================================================
RCS file: /home/wine/wine/dlls/shell32/brsfolder.c,v
retrieving revision 1.53
diff -u -r1.53 brsfolder.c
--- dlls/shell32/brsfolder.c	7 Oct 2004 03:06:48 -0000	1.53
+++ dlls/shell32/brsfolder.c	30 Nov 2004 14:57:03 -0000
@@ -1,5 +1,6 @@
 /*
  * Copyright 1999 Juergen Schmied
+ * Copyright 2004 Robert van Herk
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -35,14 +36,20 @@
 #include "shellapi.h"
 #include "shresdef.h"
 
+#include "brsfolder_windows.h"
+#include "brsfolder_unix.h"
+
+#include "brsfolder.h"
+
 WINE_DEFAULT_DEBUG_CHANNEL(shell);
 
-static HWND		hwndTreeView;
-static LPBROWSEINFOW	lpBrowseInfo;
-static LPITEMIDLIST	pidlRet;
 
-static void FillTreeView(LPSHELLFOLDER lpsf, LPITEMIDLIST  lpifq, HTREEITEM hParent, \
                IEnumIDList* lpe);
-static HTREEITEM InsertTreeViewItem(IShellFolder * lpsf, LPCITEMIDLIST pidl, \
LPCITEMIDLIST pidlParent, IEnumIDList* pEnumIL, HTREEITEM hParent); +enum browsemode \
{ +  WINDOWS,
+  UNIX
+};
+
+static enum browsemode browseMode;
 
 #define SUPPORTEDFLAGS (BIF_STATUSTEXT | \
                         BIF_BROWSEFORCOMPUTER | \
@@ -50,256 +57,31 @@
                         BIF_RETURNONLYFSDIRS | \
                         BIF_BROWSEINCLUDEFILES)
 
-static inline DWORD BrowseFlagsToSHCONTF(UINT ulFlags)
-{
-    return SHCONTF_FOLDERS | (ulFlags & BIF_BROWSEINCLUDEFILES ? SHCONTF_NONFOLDERS \
                : 0);
-}
-
-static void InitializeTreeView(HWND hwndParent, LPCITEMIDLIST root)
+static void InitializeTreeView(HWND hwndParent, LPBROWSEINFOW lpbi, INSERTROOT_PROC \
insertroot_proc)  {
 	HIMAGELIST	hImageList;
-	IShellFolder *	lpsf;
-	HRESULT	hr;
-	IEnumIDList * pEnumIL = NULL;
-	LPITEMIDLIST parentofroot;
-	parentofroot = ILClone(root);
-	ILRemoveLastID(parentofroot);
 
 	hwndTreeView = GetDlgItem (hwndParent, IDD_TREEVIEW);
 	Shell_GetImageList(NULL, &hImageList);
 
-	TRACE("dlg=%p tree=%p\n", hwndParent, hwndTreeView );
+	TRACE("dlg=%p tree=%p\n", hwndParent, hwndTreeView);
 
 	if (hImageList && hwndTreeView)
 	  TreeView_SetImageList(hwndTreeView, hImageList, 0);
 
-	if (_ILIsDesktop (root)) {
-	   hr = SHGetDesktopFolder(&lpsf);
-	} else {
-	   IShellFolder *	lpsfdesktop;
-
-	   hr = SHGetDesktopFolder(&lpsfdesktop);
-	   if (SUCCEEDED(hr)) {
-	      hr = IShellFolder_BindToObject(lpsfdesktop, parentofroot, \
                0,(REFIID)&IID_IShellFolder,(LPVOID *)&lpsf);
-	      IShellFolder_Release(lpsfdesktop);
-	   }
-	}
-	if (SUCCEEDED(hr))
-	{
-	    IShellFolder * pSFRoot;
-	    if (_ILIsPidlSimple(root))
-	    {
-	        pSFRoot = lpsf;
-	        IShellFolder_AddRef(pSFRoot);
-	    }
-	    else
-	        hr = IShellFolder_BindToObject(lpsf,ILFindLastID(root),0,&IID_IShellFolder,(LPVOID \
                *)&pSFRoot);
-	    if (SUCCEEDED(hr))
-	    {
-	        hr = IShellFolder_EnumObjects(
-	            pSFRoot,
-	            hwndParent,
-	            BrowseFlagsToSHCONTF(lpBrowseInfo->ulFlags),
-	            &pEnumIL);
-	        IShellFolder_Release(pSFRoot);
-	    }
-	}
-
-	if (SUCCEEDED(hr) && hwndTreeView)
+	if (hwndTreeView)
 	{
 	  TreeView_DeleteAllItems(hwndTreeView);
 	  TreeView_Expand(hwndTreeView,
-	                  InsertTreeViewItem(lpsf, _ILIsPidlSimple(root) ? root : \
ILFindLastID(root), parentofroot, pEnumIL,  TVI_ROOT), +	                  \
insertroot_proc(hwndParent, hwndTreeView, lpbi),  TVE_EXPAND);
 	}
-
-	if (SUCCEEDED(hr))
-	  IShellFolder_Release(lpsf);
-
 	TRACE("done\n");
 }
 
-static int GetIcon(LPITEMIDLIST lpi, UINT uFlags)
-{
-	SHFILEINFOW    sfi;
-	SHGetFileInfoW((LPCWSTR)lpi, 0 ,&sfi, sizeof(SHFILEINFOW), uFlags);
-	return sfi.iIcon;
-}
-
-static void GetNormalAndSelectedIcons(LPITEMIDLIST lpifq, LPTVITEMW lpTV_ITEM)
-{
-	LPITEMIDLIST pidlDesktop = NULL;
-
-	TRACE("%p %p\n",lpifq, lpTV_ITEM);
-
-	if (!lpifq)
-	{
-	    pidlDesktop = _ILCreateDesktop();
-	    lpifq = pidlDesktop;
-	}
-
-	lpTV_ITEM->iImage = GetIcon(lpifq, SHGFI_PIDL | SHGFI_SYSICONINDEX | \
                SHGFI_SMALLICON);
-	lpTV_ITEM->iSelectedImage = GetIcon(lpifq, SHGFI_PIDL | SHGFI_SYSICONINDEX | \
                SHGFI_SMALLICON | SHGFI_OPENICON);
-
-	if (pidlDesktop)
-	    ILFree(pidlDesktop);
-
-	return;
-}
-
-typedef struct tagID
-{
-   LPSHELLFOLDER lpsfParent;
-   LPITEMIDLIST  lpi;
-   LPITEMIDLIST  lpifq;
-   IEnumIDList*  pEnumIL;
-} TV_ITEMDATA, *LPTV_ITEMDATA;
-
-static BOOL GetName(LPSHELLFOLDER lpsf, LPCITEMIDLIST lpi, DWORD dwFlags, LPWSTR \
                lpFriendlyName)
-{
-	BOOL   bSuccess=TRUE;
-	STRRET str;
-
-	TRACE("%p %p %lx %p\n", lpsf, lpi, dwFlags, lpFriendlyName);
-	if (SUCCEEDED(IShellFolder_GetDisplayNameOf(lpsf, lpi, dwFlags, &str)))
-	{
-	  if (FAILED(StrRetToStrNW(lpFriendlyName, MAX_PATH, &str, lpi)))
-	  {
-	      bSuccess = FALSE;
-	  }
-	}
-	else
-	  bSuccess = FALSE;
-
-	TRACE("-- %s\n", debugstr_w(lpFriendlyName));
-	return bSuccess;
-}
-
-static HTREEITEM InsertTreeViewItem(IShellFolder * lpsf, LPCITEMIDLIST pidl, \
                LPCITEMIDLIST pidlParent, IEnumIDList* pEnumIL, HTREEITEM hParent)
-{
-	TVITEMW 	tvi;
-	TVINSERTSTRUCTW	tvins;
-	WCHAR		szBuff[MAX_PATH];
-	LPTV_ITEMDATA	lptvid=0;
-
-	tvi.mask  = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
-
-	tvi.cChildren= pEnumIL ? 1 : 0;
-	tvi.mask |= TVIF_CHILDREN;
-
-	if (!(lptvid = (LPTV_ITEMDATA)SHAlloc(sizeof(TV_ITEMDATA))))
-	    return NULL;
-
-	if (!GetName(lpsf, pidl, SHGDN_NORMAL, szBuff))
-	    return NULL;
-
-	tvi.pszText    = szBuff;
-	tvi.cchTextMax = MAX_PATH;
-	tvi.lParam = (LPARAM)lptvid;
-
-	IShellFolder_AddRef(lpsf);
-	lptvid->lpsfParent = lpsf;
-	lptvid->lpi	= ILClone(pidl);
-	lptvid->lpifq	= pidlParent ? ILCombine(pidlParent, pidl) : ILClone(pidl);
-	lptvid->pEnumIL = pEnumIL;
-	GetNormalAndSelectedIcons(lptvid->lpifq, &tvi);
-
-	tvins.u.item       = tvi;
-	tvins.hInsertAfter = NULL;
-	tvins.hParent      = hParent;
-
-	return (HTREEITEM)TreeView_InsertItemW(hwndTreeView, &tvins);
-}
-
-static void FillTreeView(IShellFolder * lpsf, LPITEMIDLIST  pidl, HTREEITEM hParent, \
                IEnumIDList* lpe)
-{
-	HTREEITEM	hPrev = 0;
-	LPITEMIDLIST	pidlTemp = 0;
-	ULONG		ulFetched;
-	HRESULT		hr;
-	HWND		hwnd=GetParent(hwndTreeView);
-
-	TRACE("%p %p %x\n",lpsf, pidl, (INT)hParent);
-	SetCapture(GetParent(hwndTreeView));
-	SetCursor(LoadCursorA(0, (LPSTR)IDC_WAIT));
-
-	while (NOERROR == IEnumIDList_Next(lpe,1,&pidlTemp,&ulFetched))
-	{
-	    ULONG ulAttrs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER;
-	    IEnumIDList* pEnumIL = NULL;
-	    IShellFolder* pSFChild = NULL;
-	    IShellFolder_GetAttributesOf(lpsf, 1, (LPCITEMIDLIST*)&pidlTemp, &ulAttrs);
-	    if (ulAttrs & SFGAO_FOLDER)
-	    {
-	        hr = IShellFolder_BindToObject(lpsf,pidlTemp,NULL,&IID_IShellFolder,(LPVOID*)&pSFChild);
                
-	        if (SUCCEEDED(hr))
-                {
-	            hr = IShellFolder_EnumObjects(pSFChild, hwnd, \
                BrowseFlagsToSHCONTF(lpBrowseInfo->ulFlags), &pEnumIL);
-                    if (SUCCEEDED(hr))
-                    {
-                        if ((IEnumIDList_Skip(pEnumIL, 1) != S_OK) || \
                FAILED(IEnumIDList_Reset(pEnumIL)))
-                        {
-                            IEnumIDList_Release(pEnumIL);
-                            pEnumIL = NULL;
-                        }
-                    }
-                    IShellFolder_Release(pSFChild);
-                }
-	    }
-
-	    if (!(hPrev = InsertTreeViewItem(lpsf, pidlTemp, pidl, pEnumIL, hParent)))
-	        goto Done;
-	    SHFree(pidlTemp);  /* Finally, free the pidl that the shell gave us... */
-	    pidlTemp=NULL;
-	}
-
-Done:
-	ReleaseCapture();
-	SetCursor(LoadCursorW(0, (LPWSTR)IDC_ARROW));
-
-	if (pidlTemp)
-	  SHFree(pidlTemp);
-}
-
-static inline BOOL PIDLIsType(LPCITEMIDLIST pidl, PIDLTYPE type)
-{
-    LPPIDLDATA data = _ILGetDataPointer(pidl);
-    if (!data)
-        return FALSE;
-    return (data->type == type);
-}
-
-static void BrsFolder_CheckValidSelection(HWND hWndTree, LPTV_ITEMDATA lptvid)
-{
-    LPCITEMIDLIST pidl = lptvid->lpi;
-    BOOL bEnabled = TRUE;
-    DWORD dwAttributes;
-    if ((lpBrowseInfo->ulFlags & BIF_BROWSEFORCOMPUTER) &&
-        !PIDLIsType(pidl, PT_COMP))
-        bEnabled = FALSE;
-    if (lpBrowseInfo->ulFlags & BIF_RETURNFSANCESTORS)
-    {
-        dwAttributes = SFGAO_FILESYSANCESTOR | SFGAO_FILESYSTEM;
-        if (FAILED(IShellFolder_GetAttributesOf(lptvid->lpsfParent, 1, \
                (LPCITEMIDLIST*)&lptvid->lpi, &dwAttributes)) ||
-            !dwAttributes)
-            bEnabled = FALSE;
-    }
-    if (lpBrowseInfo->ulFlags & BIF_RETURNONLYFSDIRS)
-    {
-        dwAttributes = SFGAO_FOLDER | SFGAO_FILESYSTEM;
-        if (FAILED(IShellFolder_GetAttributesOf(lptvid->lpsfParent, 1, \
                (LPCITEMIDLIST*)&lptvid->lpi, &dwAttributes)) ||
-            (dwAttributes != (SFGAO_FOLDER | SFGAO_FILESYSTEM)))
-            bEnabled = FALSE;
-    }
-    SendMessageW(hWndTree, BFFM_ENABLEOK, 0, (LPARAM)bEnabled);
-}
-
 static LRESULT MsgNotify(HWND hWnd,  UINT CtlID, LPNMHDR lpnmh)
 {
 	NMTREEVIEWW	*pnmtv   = (NMTREEVIEWW *)lpnmh;
-	LPTV_ITEMDATA	lptvid;  /* Long pointer to TreeView item data */
-	IShellFolder *	lpsf2=0;
-
 
 	TRACE("%p %x %p msg=%x\n", hWnd,  CtlID, lpnmh, pnmtv->hdr.code);
 
@@ -310,14 +92,13 @@
 	      case TVN_DELETEITEMA:
 	      case TVN_DELETEITEMW:
                 TRACE("TVN_DELETEITEMA/W\n");
-	        lptvid=(LPTV_ITEMDATA)pnmtv->itemOld.lParam;
-	        IShellFolder_Release(lptvid->lpsfParent);
-	        if (lptvid->pEnumIL)
-	          IEnumIDList_Release(lptvid->pEnumIL);
-	        SHFree(lptvid->lpi);
-	        SHFree(lptvid->lpifq);
-	        SHFree(lptvid);
-	        break;
+              if (browseMode == WINDOWS) {
+                OnDeleteItem_Windows(pnmtv);
+              }
+              else {
+                OnDeleteItem_UNIX(pnmtv);
+              }
+	      break;
 
 	      case TVN_ITEMEXPANDINGA:
 	      case TVN_ITEMEXPANDINGW:
@@ -325,21 +106,25 @@
                   TRACE("TVN_ITEMEXPANDINGA/W\n");
 		  if ((pnmtv->itemNew.state & TVIS_EXPANDEDONCE))
 	            break;
-
-	          lptvid=(LPTV_ITEMDATA)pnmtv->itemNew.lParam;
-	          if (SUCCEEDED(IShellFolder_BindToObject(lptvid->lpsfParent, \
                lptvid->lpi,0,(REFIID)&IID_IShellFolder,(LPVOID *)&lpsf2)))
-	          { FillTreeView( lpsf2, lptvid->lpifq, pnmtv->itemNew.hItem, \
                lptvid->pEnumIL);
-	          }
+                  if (browseMode == WINDOWS) {
+                    OnItemExpanding_Windows(hwndTreeView, lpBrowseInfo, pnmtv);
+                  } else {
+                    OnItemExpanding_UNIX(hwndTreeView, lpBrowseInfo, pnmtv);
+                  }
 	          TreeView_SortChildren(hwndTreeView, pnmtv->itemNew.hItem, FALSE);
 		}
 	        break;
 	      case TVN_SELCHANGEDA:
 	      case TVN_SELCHANGEDW:
-	        lptvid=(LPTV_ITEMDATA)pnmtv->itemNew.lParam;
-		pidlRet = lptvid->lpifq;
-		if (lpBrowseInfo->lpfn)
-		   (lpBrowseInfo->lpfn)(hWnd, BFFM_SELCHANGED, (LPARAM)pidlRet, \
                lpBrowseInfo->lParam);
-		BrsFolder_CheckValidSelection(hWnd, lptvid);
+                if (browseMode == WINDOWS) {
+                  LPITEMIDLIST pidlRet = OnSelChanged_Windows(hWnd, lpBrowseInfo, \
pnmtv); +                  if (lpBrowseInfo->lpfn)
+		    (lpBrowseInfo->lpfn)(hWnd, BFFM_SELCHANGED, (LPARAM)pidlRet, \
lpBrowseInfo->lParam); +
+                } else {
+                  OnSelChanged_UNIX(hWnd, lpBrowseInfo, pnmtv);
+                  /*TODO: Call lpBrowseInfo->lpfn?? What to use for a pidl?*/
+                }
 	        break;
 
 	      default:
@@ -355,55 +140,21 @@
 	return 0;
 }
 
-
 /*************************************************************************
- *             BrsFolderDlgProc32  (not an exported API function)
+ * DefBrsDlgProc
+ * Dialog procedure for both the browse for folder and browse for UNIX 
+ * directory dialog. General cases get forwarded to this procedure.
  */
-static INT_PTR CALLBACK BrsFolderDlgProc(HWND hWnd, UINT msg, WPARAM wParam,
+INT_PTR DefBrsDlgProc(HWND hWnd, UINT msg, WPARAM wParam,
 				     LPARAM lParam )
 {
-	TRACE("hwnd=%p msg=%04x 0x%08x 0x%08lx\n", hWnd,  msg, wParam, lParam );
-
 	switch(msg)
-	{ case WM_INITDIALOG:
-	    pidlRet = NULL;
-	    lpBrowseInfo = (LPBROWSEINFOW) lParam;
-	    if (lpBrowseInfo->ulFlags & ~SUPPORTEDFLAGS)
-	      FIXME("flags %x not implemented\n", lpBrowseInfo->ulFlags & ~SUPPORTEDFLAGS);
-	    if (lpBrowseInfo->lpszTitle) {
-	       SetWindowTextW(GetDlgItem(hWnd, IDD_TITLE), lpBrowseInfo->lpszTitle);
-	    } else {
-	       ShowWindow(GetDlgItem(hWnd, IDD_TITLE), SW_HIDE);
-	    }
-	    if (!(lpBrowseInfo->ulFlags & BIF_STATUSTEXT))
-	       ShowWindow(GetDlgItem(hWnd, IDD_STATUS), SW_HIDE);
-
-	    InitializeTreeView(hWnd, lpBrowseInfo->pidlRoot);
-
-	    if (lpBrowseInfo->lpfn)
-	       (lpBrowseInfo->lpfn)(hWnd, BFFM_INITIALIZED, 0, lpBrowseInfo->lParam);
-
-	    return TRUE;
-
-	  case WM_NOTIFY:
+	{
+    case WM_NOTIFY:
 	    MsgNotify( hWnd, (UINT)wParam, (LPNMHDR)lParam);
 	    break;
-
-	  case WM_COMMAND:
-	    switch (wParam)
-	    { case IDOK:
-	        pdump ( pidlRet );
-		if (lpBrowseInfo->pszDisplayName)
-	            SHGetPathFromIDListW(pidlRet, lpBrowseInfo->pszDisplayName);
-	        EndDialog(hWnd, (DWORD) ILClone(pidlRet));
-	        return TRUE;
-
-	      case IDCANCEL:
-	        EndDialog(hWnd, 0);
-	        return TRUE;
-	    }
-	    break;
-	case BFFM_SETSTATUSTEXTA:
+	
+  case BFFM_SETSTATUSTEXTA:
 	   TRACE("Set status %s\n", debugstr_a((LPSTR)lParam));
 	   SetWindowTextA(GetDlgItem(hWnd, IDD_STATUS), (LPSTR)lParam);
 	   break;
@@ -439,26 +190,58 @@
 	   break;
 	}
 	return FALSE;
-}
+} 
 
+BOOL OnInitDialog(HWND hWnd, LPARAM lParam, INSERTROOT_PROC insertroot_proc) 
+{
+        lpBrowseInfo = (LPBROWSEINFOW) lParam;
+        if (lpBrowseInfo->ulFlags & ~SUPPORTEDFLAGS)
+          FIXME("flags %x not implemented\n", lpBrowseInfo->ulFlags & \
~SUPPORTEDFLAGS); +        if (lpBrowseInfo->lpszTitle) {
+          SetWindowTextW(GetDlgItem(hWnd, IDD_TITLE), lpBrowseInfo->lpszTitle);
+        } else {
+          ShowWindow(GetDlgItem(hWnd, IDD_TITLE), SW_HIDE);
+        }
+        if (!(lpBrowseInfo->ulFlags & BIF_STATUSTEXT))
+          ShowWindow(GetDlgItem(hWnd, IDD_STATUS), SW_HIDE);
+
+        InitializeTreeView(hWnd, lpBrowseInfo, insertroot_proc);
+
+        if (lpBrowseInfo->lpfn)
+          (lpBrowseInfo->lpfn)(hWnd, BFFM_INITIALIZED, 0, lpBrowseInfo->lParam);
+        return TRUE;
+}
+ 
 static const WCHAR swBrowseTempName[] = \
{'S','H','B','R','S','F','O','R','F','O','L','D','E','R','_','M','S','G','B','O','X',0};
  
-/*************************************************************************
- * SHBrowseForFolderA [SHELL32.@]
- * SHBrowseForFolder  [SHELL32.@]
+/*
+ * This function is both used for Windows browsing and UNIX browsing 
  */
-LPITEMIDLIST WINAPI SHBrowseForFolderA (LPBROWSEINFOA lpbi)
+static INT_PTR BrowseW (LPBROWSEINFOW lpbi, DLGPROC dlgproc, enum browsemode \
aBrowseMode) +{
+        INT_PTR ret;
+       
+        browseMode = aBrowseMode;
+        
+        ret = DialogBoxParamW(shell32_hInstance,
+	  swBrowseTempName, lpbi->hwndOwner,
+	  dlgproc, (INT)lpbi);
+        return ret;
+}
+
+/*
+ * This function is both used for Windows browsing and UNIX browsing 
+ */
+static INT_PTR BrowseA (LPBROWSEINFOA lpbi, DLGPROC dlgproc, enum browsemode \
aBrowseMode)  {
 	BROWSEINFOW bi;
-	LPITEMIDLIST lpid;
+	INT_PTR ret;
 	INT len;
-	
+        
+        browseMode = aBrowseMode;
+  
 	TRACE("(%p{lpszTitle=%s,owner=%p})\n", lpbi,
 	    lpbi ? debugstr_a(lpbi->lpszTitle) : NULL, lpbi ? lpbi->hwndOwner : NULL);
-
-	if (!lpbi)
-	  return NULL;
-
 	bi.hwndOwner = lpbi->hwndOwner;
 	bi.pidlRoot = lpbi->pidlRoot;
 	if (lpbi->pszDisplayName)
@@ -483,9 +266,9 @@
 	bi.lpfn = lpbi->lpfn;
 	bi.lParam = lpbi->lParam;
 	bi.iImage = lpbi->iImage;
-	lpid = (LPITEMIDLIST) DialogBoxParamW(shell32_hInstance,
-	                                      swBrowseTempName, lpbi->hwndOwner,
-	                                      BrsFolderDlgProc, (INT)&bi);
+	ret = DialogBoxParamW(shell32_hInstance,
+	                      swBrowseTempName, lpbi->hwndOwner,
+	                      dlgproc, (INT)&bi);
 	if (bi.pszDisplayName)
 	{
 	  WideCharToMultiByte(CP_ACP, 0, bi.pszDisplayName, -1, lpbi->pszDisplayName, \
MAX_PATH, 0, NULL); @@ -496,7 +279,19 @@
 	  HeapFree(GetProcessHeap(), 0, (LPVOID)bi.lpszTitle);
 	}
 	lpbi->iImage = bi.iImage;
-	return lpid;
+	return ret;
+}
+
+/*************************************************************************
+ * SHBrowseForFolderA [SHELL32.@]
+ * SHBrowseForFolder  [SHELL32.@]
+ */
+LPITEMIDLIST WINAPI SHBrowseForFolderA (LPBROWSEINFOA lpbi)
+{
+        if (!lpbi)
+	  return NULL;
+
+        return (LPITEMIDLIST) BrowseA (lpbi, BrsFolderDlgProc_Windows, WINDOWS);
 }
 
 
@@ -508,10 +303,64 @@
 	TRACE("((%p->{lpszTitle=%s,owner=%p})\n", lpbi,
 	    lpbi ? debugstr_w(lpbi->lpszTitle) : NULL, lpbi ? lpbi->hwndOwner : 0);
 
-	if (!lpbi)
+        if (!lpbi)
 	  return NULL;
+            
+	return (LPITEMIDLIST) BrowseW (lpbi, BrsFolderDlgProc_Windows, WINDOWS);
+}
+
+/*************************************************************************
+ * wine_shell_browse_for_UNIX_directory [SHELL32.@]
+ */
+BOOL WINAPI wine_shell_browse_for_UNIX_directoryA (LPBROWSEINFOA lpbi)
+{
+        if (!lpbi)
+	  return FALSE;
+  
+        /*For UNIX browsing, pidls are not used. Hence, if the
+          user passes a pidl that should be root for this browse
+          anyway, we refuse to show the dialog:*/
+        if (lpbi->pidlRoot)
+        {
+          ERR("pildRoot must be set to NULL for UNIX browsing.\n");
+          return FALSE;
+        }
+  
+        /*For UNIX browsing, we always use the pszDiplayName to RETURN 
+          the chosen path in, thus:*/
+        if (!lpbi->pszDisplayName)
+        {
+          ERR("pszDisplayName must be set for UNIX browsing.\n");
+          return FALSE;
+        }
+  
+        return (BOOL) BrowseA (lpbi, BrsDirectoryDlgProc_UNIX, UNIX);
+}
+
+/*************************************************************************
+ * wine_shell_browse_for_UNIX_directoryW [SHELL32.@]
+ */
+BOOL WINAPI wine_shell_browse_for_UNIX_directoryW (LPBROWSEINFOW lpbi)
+{
+          if (!lpbi)
+	    return FALSE;
+          
+          /*For UNIX browsing, pidls are not used. Hence, if the
+            user passes a pidl that should be root for this browse
+            anyway, we refuse to show the dialog:*/
+          if (lpbi->pidlRoot)
+          {
+            ERR("pildRoot must be set to NULL for UNIX browsing.\n");
+            return FALSE;
+          }
+  
+          /*For UNIX browsing, we always use the pszDiplayName to RETURN 
+            the chosen path in, thus:*/
+          if (!lpbi->pszDisplayName)
+          {
+            ERR("pszDisplayName must be set for UNIX browsing.\n");
+            return FALSE;
+          }
 
-	return (LPITEMIDLIST) DialogBoxParamW(shell32_hInstance,
-	                                      swBrowseTempName, lpbi->hwndOwner,
-	                                      BrsFolderDlgProc, (INT)lpbi);
+          return (BOOL) BrowseW (lpbi, BrsDirectoryDlgProc_UNIX, UNIX);
 }
Index: dlls/shell32/shell32.spec
===================================================================
RCS file: /home/wine/wine/dlls/shell32/shell32.spec,v
retrieving revision 1.89
diff -u -r1.89 shell32.spec
--- dlls/shell32/shell32.spec	4 Nov 2004 04:54:08 -0000	1.89
+++ dlls/shell32/shell32.spec	30 Nov 2004 14:57:03 -0000
@@ -405,6 +405,13 @@
 @ stub WOWShellExecute
 
 #
+# Some Wine specific functions
+#
+@ stdcall wine_shell_browse_for_UNIX_directory(ptr) \
wine_shell_browse_for_UNIX_directoryA +@ stdcall \
wine_shell_browse_for_UNIX_directoryA(ptr) +@ stdcall \
wine_shell_browse_for_UNIX_directoryW(ptr) +
+#
 # version 4.70 (IE3.0)
 # _WIN32_IE >= 0x0300
 #
Index: include/shlobj.h
===================================================================
RCS file: /home/wine/wine/include/shlobj.h,v
retrieving revision 1.96
diff -u -r1.96 shlobj.h
--- include/shlobj.h	4 Nov 2004 04:54:08 -0000	1.96
+++ include/shlobj.h	30 Nov 2004 14:57:05 -0000
@@ -294,6 +294,13 @@
 #define BFFM_VALIDATEFAILED WINELIB_NAME_AW(BFFM_VALIDATEFAILED)
 
 /**********************************************************************
+ * wine_shell_browse_for_UNIX_directory API
+ */
+BOOL WINAPI wine_shell_browse_for_UNIX_directoryA(LPBROWSEINFOA lpbi);
+BOOL WINAPI wine_shell_browse_for_UNIX_directoryW(LPBROWSEINFOW lpbi);
+#define wine_shell_browse_for_UNIX_directory \
WINELIB_NAME_AW(wine_shell_browse_for_UNIX_directory) +
+/**********************************************************************
  * SHCreateShellFolderViewEx API
  */
 
Index: programs/winecfg/Makefile.in
===================================================================
RCS file: /home/wine/wine/programs/winecfg/Makefile.in,v
retrieving revision 1.12
diff -u -r1.12 Makefile.in
--- programs/winecfg/Makefile.in	23 Nov 2004 13:50:23 -0000	1.12
+++ programs/winecfg/Makefile.in	30 Nov 2004 14:57:06 -0000
@@ -4,7 +4,7 @@
 VPATH     = @srcdir@
 MODULE    = winecfg.exe
 APPMODE   = -mwindows
-IMPORTS   = comdlg32 comctl32 user32 advapi32 kernel32
+IMPORTS   = comdlg32 comctl32 user32 advapi32 kernel32 shell32
 
 C_SRCS = \
 	appdefaults.c \
@@ -16,7 +16,7 @@
 	main.c \
 	properties.c \
 	winecfg.c \
-	x11drvdlg.c
+	x11drvdlg.c \
 
 RC_SRCS = winecfg.rc
 RC_BINSRC = winecfg.rc
Index: programs/winecfg/driveui.c
===================================================================
RCS file: /home/wine/wine/programs/winecfg/driveui.c,v
retrieving revision 1.1
diff -u -r1.1 driveui.c
--- programs/winecfg/driveui.c	23 Nov 2004 13:50:23 -0000	1.1
+++ programs/winecfg/driveui.c	30 Nov 2004 14:57:07 -0000
@@ -34,6 +34,8 @@
 #include <shlobj.h>
 #include <winuser.h>
 
+#include <dlgs.h>
+
 #include <wine/debug.h>
 
 #include "winecfg.h"
@@ -580,9 +582,20 @@
                     break;
 
                 case IDC_BUTTON_BROWSE_PATH:
-                    MessageBox(dialog, "", "Write me!", MB_OK);
-                    break;
+                {
+                    LPBROWSEINFO bi;
 
+                    bi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, \
sizeof(BROWSEINFO)); +                    bi->hwndOwner = dialog;
+                    bi->pszDisplayName = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
+                    bi->lpszTitle = "Please choose a directory"; /*FIXME: Get this \
multilingual*/ +                    if (wine_shell_browse_for_UNIX_directory(bi))
+                      set_text(dialog, IDC_EDIT_PATH, bi->pszDisplayName);
+
+                    HeapFree(GetProcessHeap(), 0, bi->pszDisplayName);
+                    HeapFree(GetProcessHeap(), 0, bi);
+                    break;
+                }
                 case IDC_RADIO_ASSIGN:
                 {
                     char *str;
--- /dev/null	2004-04-06 15:27:52.000000000 +0200
+++ dlls/shell32/brsfolder_unix.h	2004-11-30 00:27:23.000000000 +0100
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2004 Robert van Herk
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+ 
+#ifndef __BRSFOLDER_UNIX_H__
+#define __BRSFOLDER_UNIX_H__
+
+#include "shlobj.h"
+
+inline HTREEITEM InsertRootItem_UNIX(HWND hwndParent, HWND hwndTreeView, \
LPBROWSEINFOW lpbi); +inline void OnDeleteItem_UNIX (NMTREEVIEWW *pnmtv);
+inline void OnItemExpanding_UNIX (HWND hwndTreeView, LPBROWSEINFOW lpBrowseInfo, \
NMTREEVIEWW *pnmtv); +inline void OnSelChanged_UNIX (HWND hwndTreeView, LPBROWSEINFOW \
lpBrowseInfo, NMTREEVIEWW *pnmtv); +
+INT_PTR CALLBACK BrsDirectoryDlgProc_UNIX(HWND hWnd, UINT msg, WPARAM wParam,
+				     LPARAM lParam );
+
+
+#endif
--- /dev/null	2004-04-06 15:27:52.000000000 +0200
+++ dlls/shell32/brsfolder_unix.c	2004-11-30 15:57:18.000000000 +0100
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2004 Robert van Herk
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#define COBJMACROS
+
+#include "wine/debug.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "undocshell.h"
+#include "winnls.h"
+
+#include "brsfolder.h"
+#include "unixTools.h"
+
+/* Some UNIX includes*/
+#include <sys/stat.h>  /*For IF_DIR*/
+#include <sys/param.h> /*For MAXPATHLEN*/
+
+#include "brsfolder_windows.h"
+WINE_DEFAULT_DEBUG_CHANNEL(shell);
+
+#define MAXPATHLEN_UNIX MAXPATHLEN
+typedef struct tagID_UNIX
+{
+  char* path;
+} TV_ITEMDATA_UNIX, *LPTV_ITEMDATA_UNIX;
+
+static LPTV_ITEMDATA_UNIX currLPID = 0;
+
+static HTREEITEM InsertTreeViewItem(HWND hwndTreeView, char* path, HTREEITEM \
hParent) +{
+	TRACE("Path: %s\n", path);
+        TVITEMW tvi;
+	TVINSERTSTRUCTW	tvins;
+        WCHAR szBuff[MAXPATHLEN_UNIX];
+	LPTV_ITEMDATA_UNIX lptvid = 0;
+        
+        TVITEMEXW tviParent;
+        tviParent.hItem = hParent;
+        LPTV_ITEMDATA_UNIX lptvidParent = 0;
+        if (hParent != TVI_ROOT) {
+          if (TreeView_GetItemW(hwndTreeView, &tviParent)) {
+            lptvidParent = (LPTV_ITEMDATA_UNIX) (tviParent.lParam);
+          } else
+            ERR("hParent passed, but was not found as an item in hwndTreeView\n");
+        }
+
+        MultiByteToWideChar(CP_ACP, 0, path, MAXPATHLEN_UNIX, szBuff, \
MAXPATHLEN_UNIX); +        
+        tvi.mask  = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
+
+	tvi.cChildren= 1;
+	tvi.mask |= TVIF_CHILDREN;
+
+	if (!(lptvid = (LPTV_ITEMDATA_UNIX)SHAlloc(sizeof(TV_ITEMDATA_UNIX))))
+	    return NULL;
+
+	tvi.pszText    = szBuff;
+	tvi.cchTextMax = MAX_PATH;
+	tvi.lParam = (LPARAM)lptvid;
+
+        lptvid->path = SHAlloc(MAXPATHLEN_UNIX);
+        if (lptvidParent) {
+          /*Concatenate path of parent to path of inserted node*/
+          strncpy(lptvid->path, lptvidParent->path, MAXPATHLEN_UNIX);
+          strncpy(lptvid->path + strlen(lptvidParent->path), path, MAXPATHLEN_UNIX - \
strlen(lptvidParent->path)); +        }
+        else
+          strncpy(lptvid->path, path, MAXPATHLEN_UNIX);
+        
+        /*Include trailing slash:*/
+        if ((strncmp(lptvid->path + (strlen(lptvid->path) - 1), "/", 1)) != 0)
+          strncpy(lptvid->path + strlen(lptvid->path), "/", MAXPATHLEN_UNIX - \
strlen(lptvid->path)); +
+        /*GetNormalAndSelectedIcons(lptvid->lpifq, &tvi); TODO: fetch icons*/
+
+	tvins.item         = tvi;
+	tvins.hInsertAfter = NULL;
+	tvins.hParent      = hParent;
+
+	return (HTREEITEM)TreeView_InsertItemW(hwndTreeView, &tvins);
+}
+
+inline HTREEITEM InsertRootItem_UNIX(HWND hwndParent, HWND hwndTreeView, \
LPBROWSEINFOW lpbi) +{
+        return InsertTreeViewItem(hwndTreeView, "/", TVI_ROOT);
+}
+
+inline void OnItemExpanding_UNIX (HWND hwndTreeView, LPBROWSEINFOW lpBrowseInfo, \
NMTREEVIEWW *pnmtv) { +        LPTV_ITEMDATA_UNIX lptvid = \
(LPTV_ITEMDATA_UNIX)pnmtv->itemNew.lParam; +        UNIXTOOLS_DIRDATA dirdata;
+        char filename [MAXPATHLEN_UNIX];
+        openDirectory(lptvid->path, S_IFDIR, &dirdata);
+        TRACE ("Directory is: \"%s\"\n", lptvid->path);
+        while (hasNextFile(&dirdata)) {
+          getNextFile(&dirdata, filename, MAXPATHLEN_UNIX);
+          TRACE ("alive %s\n", filename);
+          InsertTreeViewItem (hwndTreeView, filename, pnmtv->itemNew.hItem);
+          TRACE ("File read: %s\n", filename);
+        }
+        closeDirectory(&dirdata);
+}
+
+inline void OnDeleteItem_UNIX (NMTREEVIEWW *pnmtv) {
+        LPTV_ITEMDATA_UNIX lptvid = (LPTV_ITEMDATA_UNIX)pnmtv->itemOld.lParam;
+        SHFree(lptvid->path);
+	SHFree(lptvid);
+}
+
+inline void OnSelChanged_UNIX (HWND hwndTreeView, LPBROWSEINFOW lpBrowseInfo, \
NMTREEVIEWW *pnmtv) { +          LPTV_ITEMDATA_UNIX \
lptvid=(LPTV_ITEMDATA_UNIX)pnmtv->itemNew.lParam; +	  \
/*BrsFolder_CheckValidSelection(hwndTreeView, lpBrowseInfo, lptvid); TODO: check for \
valid selection*/ +          currLPID = lptvid;
+}
+
+
+INT_PTR CALLBACK BrsDirectoryDlgProc_UNIX(HWND hWnd, UINT msg, WPARAM wParam,
+				     LPARAM lParam )
+{
+        switch(msg)
+	{
+          case WM_INITDIALOG:
+            currLPID = NULL;
+            return OnInitDialog(hWnd, lParam, InsertRootItem_UNIX);
+          case WM_COMMAND:
+	    switch (wParam)
+	    { case IDOK:
+	        if (lpBrowseInfo->pszDisplayName)
+                  if (currLPID) {
+                    TRACE("Selected UNIX dir: %s\n", currLPID->path);
+                    MultiByteToWideChar(CP_ACP, 0, currLPID->path, MAXPATHLEN_UNIX, \
lpBrowseInfo->pszDisplayName, MAX_PATH); +                  }
+	        EndDialog(hWnd, (DWORD) TRUE);
+	        return TRUE;
+	      case IDCANCEL:
+	        EndDialog(hWnd, (DWORD) FALSE);
+	        return TRUE;
+	    }
+	    break;
+	default:
+	  return DefBrsDlgProc(hWnd, msg, wParam, lParam);
+	}
+  return FALSE;
+}
--- /dev/null	2004-04-06 15:27:52.000000000 +0200
+++ dlls/shell32/brsfolder.h	2004-11-30 15:56:40.000000000 +0100
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2004 Robert van Herk
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+ 
+#ifndef __BRSFOLDER_H__
+#define __BRSFOLDER_H__
+
+#include "shlobj.h"
+
+LPBROWSEINFOW lpBrowseInfo;
+HWND hwndTreeView;
+
+typedef HTREEITEM (*INSERTROOT_PROC)(HWND hwndParent, HWND hwndTreeView, \
LPBROWSEINFOW lpbi); +
+INT_PTR DefBrsDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
+BOOL OnInitDialog(HWND hWnd, LPARAM lParam, INSERTROOT_PROC insertroot_proc);
+#endif
--- /dev/null	2004-04-06 15:27:52.000000000 +0200
+++ dlls/shell32/brsfolder_windows.h	2004-11-30 15:57:28.000000000 +0100
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2004 Robert van Herk
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+ 
+#ifndef __BRSFOLDER_WINDOWS_H__
+#define __BRSFOLDER_WINDOWS_H__
+
+#include "shlobj.h"
+
+HTREEITEM InsertRootItem_Windows(HWND hwndParent, HWND hwndTreeView, LPBROWSEINFOW \
lpbi); +inline void OnDeleteItem_Windows (NMTREEVIEWW *pnmtv);
+inline void OnItemExpanding_Windows (HWND hwndTreeView, LPBROWSEINFOW lpBrowseInfo, \
NMTREEVIEWW *pnmtv); +inline LPITEMIDLIST OnSelChanged_Windows (HWND hwndTreeView, \
LPBROWSEINFOW lpBrowseInfo, NMTREEVIEWW *pnmtv); +INT_PTR CALLBACK \
BrsFolderDlgProc_Windows(HWND hWnd, UINT msg, WPARAM wParam, +				     LPARAM lParam \
); +
+typedef struct tagID_Windows
+{
+   LPSHELLFOLDER lpsfParent;
+   LPITEMIDLIST  lpi;
+   LPITEMIDLIST  lpifq;
+   IEnumIDList*  pEnumIL;
+} TV_ITEMDATA_WINDOWS, *LPTV_ITEMDATA_WINDOWS;
+
+
+#endif
--- /dev/null	2004-04-06 15:27:52.000000000 +0200
+++ dlls/shell32/brsfolder_windows.c	2004-11-30 15:56:25.000000000 +0100
@@ -0,0 +1,328 @@
+/*
+ * Copyright 2004 Robert van Herk
+ * Copyright 1999 Juergen Schmied
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * FIXME:
+ *  - many memory leaks
+ */
+
+#define COBJMACROS
+
+#include "wine/debug.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "undocshell.h"
+
+#include "shlguid.h"
+#include "pidl.h"
+#include "shell32_main.h"
+#include "shellapi.h"
+#include "shresdef.h"
+
+#include "brsfolder.h"
+
+#include "brsfolder_windows.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(shell);
+
+LPITEMIDLIST pidlRet;
+
+static inline DWORD BrowseFlagsToSHCONTF(UINT ulFlags)
+{
+    return SHCONTF_FOLDERS | (ulFlags & BIF_BROWSEINCLUDEFILES ? SHCONTF_NONFOLDERS \
: 0); +}
+
+static BOOL GetName(LPSHELLFOLDER lpsf, LPCITEMIDLIST lpi, DWORD dwFlags, LPWSTR \
lpFriendlyName) +{
+	BOOL   bSuccess=TRUE;
+	STRRET str;
+
+	TRACE("%p %p %lx %p\n", lpsf, lpi, dwFlags, lpFriendlyName);
+	if (SUCCEEDED(IShellFolder_GetDisplayNameOf(lpsf, lpi, dwFlags, &str)))
+	{
+	  if (FAILED(StrRetToStrNW(lpFriendlyName, MAX_PATH, &str, lpi)))
+	  {
+	      bSuccess = FALSE;
+	  }
+	}
+	else
+	  bSuccess = FALSE;
+
+	TRACE("-- %s\n", debugstr_w(lpFriendlyName));
+	return bSuccess;
+}
+
+static int GetIcon(LPITEMIDLIST lpi, UINT uFlags)
+{
+	SHFILEINFOW    sfi;
+	SHGetFileInfoW((LPCWSTR)lpi, 0 ,&sfi, sizeof(SHFILEINFOW), uFlags);
+	return sfi.iIcon;
+}
+
+static void GetNormalAndSelectedIcons(LPITEMIDLIST lpifq, LPTVITEMW lpTV_ITEM)
+{
+	LPITEMIDLIST pidlDesktop = NULL;
+
+	TRACE("%p %p\n",lpifq, lpTV_ITEM);
+
+	if (!lpifq)
+	{
+	    pidlDesktop = _ILCreateDesktop();
+	    lpifq = pidlDesktop;
+	}
+
+	lpTV_ITEM->iImage = GetIcon(lpifq, SHGFI_PIDL | SHGFI_SYSICONINDEX | \
SHGFI_SMALLICON); +	lpTV_ITEM->iSelectedImage = GetIcon(lpifq, SHGFI_PIDL | \
SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_OPENICON); +
+	if (pidlDesktop)
+	    ILFree(pidlDesktop);
+
+	return;
+}
+
+static HTREEITEM InsertTreeViewItem(HWND hwndTreeView, IShellFolder * lpsf, \
LPCITEMIDLIST pidl, LPCITEMIDLIST pidlParent, IEnumIDList* pEnumIL, HTREEITEM \
hParent) +{
+	TVITEMW 	tvi;
+	TVINSERTSTRUCTW	tvins;
+	WCHAR		szBuff[MAX_PATH];
+	LPTV_ITEMDATA_WINDOWS lptvid=0;
+
+	tvi.mask  = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
+
+	tvi.cChildren= pEnumIL ? 1 : 0;
+	tvi.mask |= TVIF_CHILDREN;
+
+	if (!(lptvid = (LPTV_ITEMDATA_WINDOWS)SHAlloc(sizeof(TV_ITEMDATA_WINDOWS))))
+	    return NULL;
+
+	if (!GetName(lpsf, pidl, SHGDN_NORMAL, szBuff))
+	    return NULL;
+
+	tvi.pszText    = szBuff;
+	tvi.cchTextMax = MAX_PATH;
+	tvi.lParam = (LPARAM)lptvid;
+
+	IShellFolder_AddRef(lpsf);
+	lptvid->lpsfParent = lpsf;
+	lptvid->lpi	= ILClone(pidl);
+	lptvid->lpifq	= pidlParent ? ILCombine(pidlParent, pidl) : ILClone(pidl);
+	lptvid->pEnumIL = pEnumIL;
+	GetNormalAndSelectedIcons(lptvid->lpifq, &tvi);
+
+	tvins.item         = tvi;
+	tvins.hInsertAfter = NULL;
+	tvins.hParent      = hParent;
+
+	return (HTREEITEM)TreeView_InsertItemW(hwndTreeView, &tvins);
+}
+
+static inline BOOL PIDLIsType(LPCITEMIDLIST pidl, PIDLTYPE type)
+{
+    LPPIDLDATA data = _ILGetDataPointer(pidl);
+    if (!data)
+        return FALSE;
+    return (data->type == type);
+}
+
+static void BrsFolder_CheckValidSelection(HWND hWndTree, LPBROWSEINFOW lpBrowseInfo, \
LPTV_ITEMDATA_WINDOWS lptvid) +{
+    LPCITEMIDLIST pidl = lptvid->lpi;
+    BOOL bEnabled = TRUE;
+    DWORD dwAttributes;
+    if ((lpBrowseInfo->ulFlags & BIF_BROWSEFORCOMPUTER) &&
+        !PIDLIsType(pidl, PT_COMP))
+        bEnabled = FALSE;
+    if (lpBrowseInfo->ulFlags & BIF_RETURNFSANCESTORS)
+    {
+        dwAttributes = SFGAO_FILESYSANCESTOR | SFGAO_FILESYSTEM;
+        if (FAILED(IShellFolder_GetAttributesOf(lptvid->lpsfParent, 1, \
(LPCITEMIDLIST*)&lptvid->lpi, &dwAttributes)) || +            !dwAttributes)
+            bEnabled = FALSE;
+    }
+    if (lpBrowseInfo->ulFlags & BIF_RETURNONLYFSDIRS)
+    {
+        dwAttributes = SFGAO_FOLDER | SFGAO_FILESYSTEM;
+        if (FAILED(IShellFolder_GetAttributesOf(lptvid->lpsfParent, 1, \
(LPCITEMIDLIST*)&lptvid->lpi, &dwAttributes)) || +            (dwAttributes != \
(SFGAO_FOLDER | SFGAO_FILESYSTEM))) +            bEnabled = FALSE;
+    }
+    SendMessageW(hWndTree, BFFM_ENABLEOK, 0, (LPARAM)bEnabled);
+}
+
+HTREEITEM InsertRootItem_Windows(HWND hwndParent, HWND hwndTreeView, LPBROWSEINFOW \
lpbi) +{
+        HTREEITEM out = 0;
+	IShellFolder *	lpsf;
+	HRESULT	hr;
+	IEnumIDList * pEnumIL = NULL;
+        LPCITEMIDLIST root = lpbi->pidlRoot;
+	LPITEMIDLIST parentofroot;
+  
+        TRACE("dlg=%p tree=%p lpbi=%p\n", hwndParent, hwndTreeView, lpbi);
+    
+	parentofroot = ILClone(root);
+	ILRemoveLastID(parentofroot);
+
+	if (_ILIsDesktop (root)) {
+	   hr = SHGetDesktopFolder(&lpsf);
+	} else {
+	   IShellFolder *	lpsfdesktop;
+
+	   hr = SHGetDesktopFolder(&lpsfdesktop);
+	   if (SUCCEEDED(hr)) {
+	      hr = IShellFolder_BindToObject(lpsfdesktop, parentofroot, \
0,(REFIID)&IID_IShellFolder,(LPVOID *)&lpsf); +	      \
IShellFolder_Release(lpsfdesktop); +	   }
+	}
+	if (SUCCEEDED(hr))
+	{
+	    IShellFolder * pSFRoot;
+	    if (_ILIsPidlSimple(root))
+	    {
+	        pSFRoot = lpsf;
+	        IShellFolder_AddRef(pSFRoot);
+	    }
+	    else
+	        hr = IShellFolder_BindToObject(lpsf,ILFindLastID(root),0,&IID_IShellFolder,(LPVOID \
*)&pSFRoot); +	    if (SUCCEEDED(hr))
+	    {
+	        hr = IShellFolder_EnumObjects(
+	            pSFRoot,
+	            hwndParent,
+	            BrowseFlagsToSHCONTF(lpbi->ulFlags),
+	            &pEnumIL);
+	        IShellFolder_Release(pSFRoot);
+	    }
+	}
+
+	if (SUCCEEDED(hr) && hwndTreeView)
+	{
+	  out = InsertTreeViewItem(hwndTreeView, lpsf, _ILIsPidlSimple(root) ? root : \
ILFindLastID(root), parentofroot, pEnumIL,  TVI_ROOT); +	}
+
+	if (SUCCEEDED(hr))
+	  IShellFolder_Release(lpsf);
+
+	TRACE("done\n");
+        return out;
+}
+
+static void FillTreeView(HWND hwndTreeView, LPBROWSEINFOW lpbi, IShellFolder * lpsf, \
LPITEMIDLIST  pidl, HTREEITEM hParent, IEnumIDList* lpe) +{
+	HTREEITEM	hPrev = 0;
+	LPITEMIDLIST	pidlTemp = 0;
+	ULONG		ulFetched;
+	HRESULT		hr;
+	HWND		hwnd=GetParent(hwndTreeView);
+
+	TRACE("%p %p %x\n",lpsf, pidl, (INT)hParent);
+	SetCapture(GetParent(hwndTreeView));
+	SetCursor(LoadCursorA(0, (LPSTR)IDC_WAIT));
+
+	while (NOERROR == IEnumIDList_Next(lpe,1,&pidlTemp,&ulFetched))
+	{
+	    ULONG ulAttrs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER;
+	    IEnumIDList* pEnumIL = NULL;
+	    IShellFolder* pSFChild = NULL;
+	    IShellFolder_GetAttributesOf(lpsf, 1, (LPCITEMIDLIST*)&pidlTemp, &ulAttrs);
+	    if (ulAttrs & SFGAO_FOLDER)
+	    {
+	        hr = IShellFolder_BindToObject(lpsf,pidlTemp,NULL,&IID_IShellFolder,(LPVOID*)&pSFChild);
 +	        if (SUCCEEDED(hr))
+                {
+	            hr = IShellFolder_EnumObjects(pSFChild, hwnd, \
BrowseFlagsToSHCONTF(lpbi->ulFlags), &pEnumIL); +                    if \
(SUCCEEDED(hr)) +                    {
+                        if ((IEnumIDList_Skip(pEnumIL, 1) != S_OK) || \
FAILED(IEnumIDList_Reset(pEnumIL))) +                        {
+                            IEnumIDList_Release(pEnumIL);
+                            pEnumIL = NULL;
+                        }
+                    }
+                    IShellFolder_Release(pSFChild);
+                }
+	    }
+
+	    if (!(hPrev = InsertTreeViewItem(hwndTreeView, lpsf, pidlTemp, pidl, pEnumIL, \
hParent))) +	        goto Done;
+	    SHFree(pidlTemp);  /* Finally, free the pidl that the shell gave us... */
+	    pidlTemp=NULL;
+	}
+
+Done:
+	ReleaseCapture();
+	SetCursor(LoadCursorW(0, (LPWSTR)IDC_ARROW));
+
+	if (pidlTemp)
+	  SHFree(pidlTemp);
+}
+
+inline void OnDeleteItem_Windows (NMTREEVIEWW *pnmtv) {
+                  LPTV_ITEMDATA_WINDOWS lptvid = \
(LPTV_ITEMDATA_WINDOWS)pnmtv->itemOld.lParam; +	          \
IShellFolder_Release(lptvid->lpsfParent); +	          if (lptvid->pEnumIL)
+	            IEnumIDList_Release(lptvid->pEnumIL);
+	          SHFree(lptvid->lpi);
+	          SHFree(lptvid->lpifq);
+	          SHFree(lptvid);
+}
+
+inline void OnItemExpanding_Windows (HWND hwndTreeView, LPBROWSEINFOW lpBrowseInfo, \
NMTREEVIEWW *pnmtv) { +        IShellFolder * lpsf2=0;
+	LPTV_ITEMDATA_WINDOWS lptvid=(LPTV_ITEMDATA_WINDOWS)pnmtv->itemNew.lParam;
+	if (SUCCEEDED(IShellFolder_BindToObject(lptvid->lpsfParent, \
lptvid->lpi,0,(REFIID)&IID_IShellFolder,(LPVOID *)&lpsf2))) +	{ \
FillTreeView(hwndTreeView, lpBrowseInfo,lpsf2, lptvid->lpifq, pnmtv->itemNew.hItem, \
lptvid->pEnumIL); +	}
+}
+
+inline LPITEMIDLIST OnSelChanged_Windows (HWND hwndTreeView, LPBROWSEINFOW \
lpBrowseInfo, NMTREEVIEWW *pnmtv) { +          LPTV_ITEMDATA_WINDOWS \
lptvid=(LPTV_ITEMDATA_WINDOWS)pnmtv->itemNew.lParam; +	  LPITEMIDLIST out = \
lptvid->lpifq; +	  BrsFolder_CheckValidSelection(hwndTreeView, lpBrowseInfo, lptvid);
+          pidlRet = out;
+          return out;
+}
+
+INT_PTR CALLBACK BrsFolderDlgProc_Windows(HWND hWnd, UINT msg, WPARAM wParam,
+				     LPARAM lParam )
+{
+	TRACE("hwnd=%p msg=%04x 0x%08x 0x%08lx\n", hWnd,  msg, wParam, lParam );
+
+	switch(msg)
+	{
+    case WM_INITDIALOG:
+	    pidlRet = NULL;
+            return OnInitDialog(hWnd, lParam, InsertRootItem_Windows);
+	  case WM_COMMAND:
+	    switch (wParam)
+	    { case IDOK:
+	        pdump ( pidlRet );
+		if (lpBrowseInfo->pszDisplayName)
+	            SHGetPathFromIDListW(pidlRet, lpBrowseInfo->pszDisplayName);
+	        EndDialog(hWnd, (DWORD) ILClone(pidlRet));
+	        return TRUE;
+
+	      case IDCANCEL:
+	        EndDialog(hWnd, 0);
+	        return TRUE;
+	    }
+	    break;
+	default:
+	   return DefBrsDlgProc(hWnd, msg, wParam, lParam);
+	}
+  return FALSE;
+}
--- /dev/null	2004-04-06 15:27:52.000000000 +0200
+++ dlls/shell32/unixTools.h	2004-11-30 12:19:08.000000000 +0100
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2004 Robert van Herk
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __UNIXTOOLS_H__
+#define __UNIXTOOLS_H__
+
+#include <dirent.h>
+
+typedef struct tagDIR
+{
+  char* currentFile;
+  char* dirname;
+  DIR* dp;
+  int open;
+  int fileTypeMask;
+} UNIXTOOLS_DIRDATA, *LP_UNIXTOOLS_DIRDATA;
+
+void openDirectory(char* dirname, int fileTypeMask, LP_UNIXTOOLS_DIRDATA dirdata);
+void closeDirectory(LP_UNIXTOOLS_DIRDATA dirdata);
+inline int hasNextFile(LP_UNIXTOOLS_DIRDATA dirdata);
+inline void getNextFile(LP_UNIXTOOLS_DIRDATA dirdata, char* buff, int maxSize);
+
+#endif
--- /dev/null	2004-04-06 15:27:52.000000000 +0200
+++ dlls/shell32/unixTools.c	2004-11-30 15:55:34.000000000 +0100
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2004 Robert van Herk
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include "wine/debug.h"
+
+#include "unixTools.h"
+
+/*
+ * Helper functions to read out UNIX directory listings.
+ * Hence: no Win32 code here, except for some wine traces
+ */
+
+WINE_DEFAULT_DEBUG_CHANNEL(shell);
+ 
+static void prepNextFile(LP_UNIXTOOLS_DIRDATA dirdata)
+{
+	TRACE("hallo\n");
+
+        struct dirent *dirp;
+        struct stat sbuf;
+        char fullName[MAXPATHLEN];
+        int len;
+        strncpy(fullName, dirdata->dirname, MAXPATHLEN); /*The part of the path from \
the root*/ +        /*Include trailing slash:*/
+        if ((strncmp(fullName + (strlen(fullName) - 1), "/", 1)) != 0)
+          strncpy(fullName + strlen(fullName), "/", MAXPATHLEN - strlen(fullName));
+        len = strlen(fullName);
+        
+        int done = 0;
+        while (!done) {
+          if ((dirp=readdir(dirdata->dp))!=NULL) {
+            /* We are done, if we found an entry of the correct type: */            
+            if (strcmp(dirp->d_name, ".") == 0) continue;  /*Ignore "." */
+            if (strcmp(dirp->d_name, "..") == 0) continue; /*Ignore ".." */
+            strncpy(fullName + len, dirp->d_name, MAXPATHLEN - len);
+            if (stat(fullName, &sbuf) != 0) continue;      /*Couldn't get stats of \
the file.*/ +            done = ((sbuf.st_mode & S_IFMT) & dirdata->fileTypeMask);
+            if (done) {
+              strncpy(dirdata->currentFile, dirp->d_name, MAXPATHLEN);
+              dirdata->open = 1;
+            }
+          } else {
+            dirdata->open = 0;
+            done = 1;
+          }
+        }
+}
+
+void openDirectory(char* dirname, int fileTypeMask, LP_UNIXTOOLS_DIRDATA dirdata)
+{
+        dirdata->currentFile = malloc(MAXPATHLEN);
+        dirdata->dirname = malloc(MAXPATHLEN);
+        if ((dirdata->dp = opendir(dirname)) != NULL)
+        {
+          dirdata->fileTypeMask = fileTypeMask;
+          strncpy(dirdata->dirname, dirname, MAXPATHLEN);
+          prepNextFile(dirdata);
+        } else
+          dirdata->open = 0;
+}
+
+void closeDirectory(LP_UNIXTOOLS_DIRDATA dirdata) {
+        closedir(dirdata->dp);
+        free(dirdata->currentFile);
+        free(dirdata->dirname);
+}
+
+inline int hasNextFile(LP_UNIXTOOLS_DIRDATA dirdata)
+{
+  return (dirdata->open == 1);
+}
+
+inline void getNextFile(LP_UNIXTOOLS_DIRDATA dirdata, char* buff, int maxSize) {
+  strncpy(buff, dirdata->currentFile, maxSize);
+  prepNextFile(dirdata);
+}



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic