Sync to Wine-0_9_3:
Michael Jung <mjung@iss.tu-darmstadt.de>
- Use the ANSI codepage in IShellFolder::GetDisplayNameOf.
- Implemented scrolling during drag&drop for the shellview class.
- Use GetUIObjectOf instead of BindToObject to get a IDropTarget object.
- Register the shell view itself as the drop target, not it's parent folder.
  Forward drag&drop method calls to the folder currently under the cursor.
- Initialize OLE instead of just COM, in order to enable Drag & Drop.
- Modified KeyStateToDropEffect macro to match native shellview's
  behaviour.
- Also scan HKEY_CURRENT_USER for shell namespace extensions in Desktop
  folder.
  Fixed a handle leak in case of failing AddToEnumList call.
- Also scan HKEY_CURRENT_USER for shell namespace extensions in
  MyComputer.
- Enhanced UnixFolder's IDropTarget implementation.
  Use STATIC_CAST macro more consistently.
- Initial stubbed implementation of UnixFolder's IDropTarget interface.
Francois Gouget <fgouget@free.fr>
- Assorted spelling fixes.
Ge van Geldorp <gvg@reactos.org>
- Load shortcut icon by resource id instead of by icon index.
- Other code in shlexec.c (e.g. the extension handling code in
  ShellExecute_GetClassKey) expects sei->lpFile to not be enclosed in
  quotes.
Martin Fuchs <martin-fuchs@gmx.net>
- Correctly call HCR_GetFolderAttributes() in SHELL32_GetItemAttributes().
  Directly return the correct "My Computer" attributes in
  ISF_Desktop_fnGetAttributesOf().
  Remove "todo_wine" from the "My Computer" attributes test case.
  Add test case for retrieving the file system path from the
  CSIDL_PROGRAM_FILES PIDL using SHGetPathFromIDListW().
- Fix context menu handling for more than one entry in order to repair
  .lnk-file execution: Don't break at the first non-matching entry.
Markus Gömmel <m.goemmel@compulab.de>
- Added CSIDL_MYVIDEO|MYPICTURES|MYMUSIC to _SHRegisterUserShellFolders.
Modified: trunk/reactos/lib/shell32/iconcache.c
Modified: trunk/reactos/lib/shell32/shell32_main.h
Modified: trunk/reactos/lib/shell32/shellpath.c
Modified: trunk/reactos/lib/shell32/shfldr_desktop.c
Modified: trunk/reactos/lib/shell32/shlexec.c
Modified: trunk/reactos/lib/shell32/shlview.c

Modified: trunk/reactos/lib/shell32/iconcache.c
--- trunk/reactos/lib/shell32/iconcache.c	2005-12-14 19:02:42 UTC (rev 20167)
+++ trunk/reactos/lib/shell32/iconcache.c	2005-12-14 19:09:44 UTC (rev 20168)
@@ -129,7 +129,10 @@
 
 	/* search for the shortcut icon only once */
 	if (s_imgListIdx == -1)
-	    s_imgListIdx = SIC_LoadOverlayIcon(-IDI_SHELL_SHORTCUT);
+	    s_imgListIdx = SIC_LoadOverlayIcon(- IDI_SHELL_SHORTCUT);
+                           /* FIXME should use icon index 29 instead of the
+                              resource id, but not all icons are present yet
+                              so we can't use icon indices */
 
 	if (s_imgListIdx != -1)
 	{

Modified: trunk/reactos/lib/shell32/shell32_main.h
--- trunk/reactos/lib/shell32/shell32_main.h	2005-12-14 19:02:42 UTC (rev 20167)
+++ trunk/reactos/lib/shell32/shell32_main.h	2005-12-14 19:09:44 UTC (rev 20168)
@@ -121,9 +121,9 @@
 	};
 
 #define KeyStateToDropEffect(kst)\
-	(((kst) & MK_CONTROL) ?\
-	(((kst) & MK_SHIFT) ? DROPEFFECT_LINK : DROPEFFECT_COPY):\
-	DROPEFFECT_MOVE)
+    ((((kst)&(MK_CONTROL|MK_SHIFT))==(MK_CONTROL|MK_SHIFT)) ? DROPEFFECT_LINK :\
+    (((kst)&(MK_CONTROL|MK_SHIFT)) ? DROPEFFECT_COPY :\
+    DROPEFFECT_MOVE))
 
 HGLOBAL RenderHDROP(LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl);
 HGLOBAL RenderSHELLIDLIST (LPITEMIDLIST pidlRoot, LPITEMIDLIST * apidl, UINT cidl);

Modified: trunk/reactos/lib/shell32/shellpath.c
--- trunk/reactos/lib/shell32/shellpath.c	2005-12-14 19:02:42 UTC (rev 20167)
+++ trunk/reactos/lib/shell32/shellpath.c	2005-12-14 19:09:44 UTC (rev 20168)
@@ -1808,12 +1808,15 @@
      CSIDL_RECENT,
      CSIDL_SENDTO,
      CSIDL_STARTMENU,
+     CSIDL_MYMUSIC,
+     CSIDL_MYVIDEO,
      CSIDL_DESKTOPDIRECTORY,
      CSIDL_NETHOOD,
      CSIDL_TEMPLATES,
      CSIDL_PRINTHOOD,
      CSIDL_COOKIES,
      CSIDL_HISTORY,
+     CSIDL_MYPICTURES
     };
     WCHAR userShellFolderPath[MAX_PATH], shellFolderPath[MAX_PATH];
     LPCWSTR pUserShellFolderPath, pShellFolderPath;

Modified: trunk/reactos/lib/shell32/shfldr_desktop.c
--- trunk/reactos/lib/shell32/shfldr_desktop.c	2005-12-14 19:02:42 UTC (rev 20167)
+++ trunk/reactos/lib/shell32/shfldr_desktop.c	2005-12-14 19:09:44 UTC (rev 20168)
@@ -428,6 +428,9 @@
     static const DWORD dwDesktopAttributes = 
         SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR |
         SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER;
+    static const DWORD dwMyComputerAttributes = 
+        SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET |
+        SFGAO_DROPTARGET | SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
 
     TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08lx))\n",
            This, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
@@ -447,6 +450,8 @@
             pdump (*apidl);
             if (_ILIsDesktop(*apidl)) { 
                 *rgfInOut &= dwDesktopAttributes;
+            } else if (_ILIsMyComputer(*apidl)) {
+                *rgfInOut &= dwMyComputerAttributes;
             } else {
                 SHELL32_GetItemAttributes (_IShellFolder_ (This), *apidl, rgfInOut);
             }

Modified: trunk/reactos/lib/shell32/shlexec.c
--- trunk/reactos/lib/shell32/shlexec.c	2005-12-14 19:02:42 UTC (rev 20167)
+++ trunk/reactos/lib/shell32/shlexec.c	2005-12-14 19:09:44 UTC (rev 20168)
@@ -1156,15 +1156,15 @@
             r = RegEnumKeyW( hkeycm, i++, szguid, 39 );
             if ( r != ERROR_SUCCESS )
                 break;
-            r = ERROR_FUNCTION_FAILED;
+
             hr = CLSIDFromString( szguid, &guid );
-            if ( FAILED( hr ) )
-                break;
-            r = ERROR_SUCCESS;
-            /* stop at the first one that succeeds in running */
-            hr = shellex_load_object_and_run( hkey, &guid, sei );
-            if ( SUCCEEDED( hr ) )
-                break;
+            if (SUCCEEDED(hr))
+            {
+                /* stop at the first one that succeeds in running */
+                hr = shellex_load_object_and_run( hkey, &guid, sei );
+                if ( SUCCEEDED( hr ) )
+                    break;
+            }
         }
         RegCloseKey( hkeycm );
     }

Modified: trunk/reactos/lib/shell32/shlview.c
--- trunk/reactos/lib/shell32/shlview.c	2005-12-14 19:02:42 UTC (rev 20167)
+++ trunk/reactos/lib/shell32/shlview.c	2005-12-14 19:09:44 UTC (rev 20168)
@@ -100,6 +100,10 @@
 	DWORD		dwAspects;
 	DWORD		dwAdvf;
 	IAdviseSink    *pAdvSink;
+        IDropTarget*    pCurDropTarget; /* The sub-item, which is currently dragged over */
+        IDataObject*    pCurDataObject; /* The dragged data-object */
+        LONG            iDragOverItem;  /* Dragged over item's index, iff pCurDropTarget != NULL */
+        UINT            iActiveTimersMask; /* Bookkeeping of activated timers for drag scrolling */
 } IShellViewImpl;
 
 static const IShellViewVtbl svvt;
@@ -190,6 +194,11 @@
 	if(pFolder) IShellFolder_AddRef(pFolder);
 	IShellFolder_QueryInterface(sv->pSFParent, &IID_IShellFolder2, (LPVOID*)&sv->pSF2Parent);
 
+        sv->pCurDropTarget = NULL;
+        sv->pCurDataObject = NULL;
+        sv->iDragOverItem = 0;
+        sv->iActiveTimersMask = 0;
+
 	TRACE("(%p)->(%p)\n",sv, pFolder);
 	return (IShellView *) sv;
 }
@@ -671,7 +680,7 @@
 	  }
 	}
 
-	if (SUCCEEDED(IShellFolder_CreateViewObject(This->pSFParent, This->hWnd, &IID_IDropTarget, (LPVOID*)&pdt)))
+        if (SUCCEEDED(IUnknown_QueryInterface((IUnknown*)&This->lpVtbl, &IID_IDropTarget, (LPVOID*)&pdt)))
 	{
 	    RegisterDragDrop(This->hWnd, pdt);
 	    IDropTarget_Release(pdt);
@@ -2169,56 +2178,176 @@
 	return IShellFolder_Release((IShellFolder*)This);
 }
 
-static HRESULT WINAPI ISVDropTarget_DragEnter(
-	IDropTarget 	*iface,
-	IDataObject	*pDataObject,
-	DWORD		grfKeyState,
-	POINTL		pt,
-	DWORD		*pdwEffect)
+/******************************************************************************
+ * scroll_timer_proc [Internal]
+ *
+ * Timer callback function for drag&drop scrolling
+ */
+
+#define IDT_UP    0x1u
+#define IDT_DOWN  0x2u
+#define IDT_LEFT  0x4u
+#define IDT_RIGHT 0x8u
+
+VOID CALLBACK scroll_timer_proc(HWND hwnd, UINT uMsg, UINT_PTR idTimer, DWORD dwTimer) {
+    switch (idTimer) {
+        case IDT_UP:
+            SendMessageW(hwnd, WM_VSCROLL, SB_LINEUP, 0);
+            break;
+        case IDT_DOWN:
+            SendMessageW(hwnd, WM_VSCROLL, SB_LINEDOWN, 0);
+            break;
+        case IDT_LEFT:
+            SendMessageW(hwnd, WM_HSCROLL, SB_LINEUP, 0);
+            break;
+        case IDT_RIGHT:
+            SendMessageW(hwnd, WM_HSCROLL, SB_LINEDOWN, 0);
+            break;
+    }
+}
+
+/******************************************************************************
+ * start_stop_timer [Internal]
+ */
+static inline void start_stop_timer(IShellViewImpl *This, UINT_PTR idTimer, BOOL fStart) {
+    if (fStart && !(This->iActiveTimersMask & idTimer)) {
+        SetTimer(This->hWndList, idTimer, 200, scroll_timer_proc);
+        This->iActiveTimersMask |= idTimer;
+    }
+    if (!fStart && This->iActiveTimersMask & idTimer) {
+        KillTimer(This->hWndList, idTimer);
+        This->iActiveTimersMask &= ~idTimer;
+    }
+}
+
+/******************************************************************************
+ * drag_notify_subitem [Internal]
+ *
+ * Figure out the shellfolder object, which is currently under the mouse cursor
+ * and notify it via the IDropTarget interface.
+ */
+
+#define SCROLLAREAWIDTH 20
+
+static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
+    DWORD *pdwEffect)
 {
+    LVHITTESTINFO htinfo;
+    LVITEMA lvItem;
+    LONG lResult;
+    HRESULT hr;
+    RECT clientRect;
 
-	IShellViewImpl *This = impl_from_IDropTarget(iface);
+    /* Map from global to client coordinates and query the index of the listview-item, which is 
+     * currently under the mouse cursor. */
+    htinfo.pt.x = pt.x;
+    htinfo.pt.y = pt.y;
+    htinfo.flags = LVHT_ONITEM;
+    ScreenToClient(This->hWndList, &htinfo.pt);
+    lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
 
-	FIXME("Stub: This=%p, DataObject=%p\n",This,pDataObject);
+    /* Start or stop the drag scrolling timers */
+    GetClientRect(This->hWndList, &clientRect);
+    start_stop_timer(This, IDT_LEFT,  htinfo.pt.x < SCROLLAREAWIDTH);
+    start_stop_timer(This, IDT_RIGHT, htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH);
+    start_stop_timer(This, IDT_UP,    htinfo.pt.y < SCROLLAREAWIDTH);
+    start_stop_timer(This, IDT_DOWN,  htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH);
 
-	return E_NOTIMPL;
+    /* If we are still over the previous sub-item, notify it via DragOver and return. */
+    if (This->pCurDropTarget && lResult == This->iDragOverItem)
+    return IDropTarget_DragOver(This->pCurDropTarget, grfKeyState, pt, pdwEffect);
+  
+    /* We've left the previous sub-item, notify it via DragLeave and Release it. */
+    if (This->pCurDropTarget) {
+        IDropTarget_DragLeave(This->pCurDropTarget);
+        IDropTarget_Release(This->pCurDropTarget);
+        This->pCurDropTarget = NULL;
+    }
+
+    This->iDragOverItem = lResult;
+    if (lResult == -1) {
+        /* We are not above one of the listview's subitems. Bind to the parent folder's
+         * DropTarget interface. */
+        hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IDropTarget, 
+                                         (LPVOID*)&This->pCurDropTarget);
+    } else {
+        /* Query the relative PIDL of the shellfolder object represented by the currently
+         * dragged over listview-item ... */
+        ZeroMemory(&lvItem, sizeof(lvItem));
+        lvItem.mask = LVIF_PARAM;
+        lvItem.iItem = lResult;
+        ListView_GetItemA(This->hWndList, &lvItem);
+
+        /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
+        hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1,
+            (LPCITEMIDLIST*)&lvItem.lParam, &IID_IDropTarget, NULL, (LPVOID*)&This->pCurDropTarget);
+    }
+
+    /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
+    if (FAILED(hr)) 
+        return hr;
+
+    /* Notify the item just entered via DragEnter. */
+    return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, pdwEffect);
 }
 
-static HRESULT WINAPI ISVDropTarget_DragOver(
-	IDropTarget	*iface,
-	DWORD		grfKeyState,
-	POINTL		pt,
-	DWORD		*pdwEffect)
+static HRESULT WINAPI ISVDropTarget_DragEnter(IDropTarget *iface, IDataObject *pDataObject,
+    DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
 {
-	IShellViewImpl *This = impl_from_IDropTarget(iface);
+    IShellViewImpl *This = impl_from_IDropTarget(iface);
 
-	FIXME("Stub: This=%p\n",This);
+    /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
+    This->pCurDataObject = pDataObject;
+    IDataObject_AddRef(pDataObject);
 
-	return E_NOTIMPL;
+    return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
 }
 
-static HRESULT WINAPI ISVDropTarget_DragLeave(
-	IDropTarget	*iface)
+static HRESULT WINAPI ISVDropTarget_DragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
+    DWORD *pdwEffect)
 {
-	IShellViewImpl *This = impl_from_IDropTarget(iface);
+    IShellViewImpl *This = impl_from_IDropTarget(iface);
+    return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
+}
 
-	FIXME("Stub: This=%p\n",This);
+static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface) {
+    IShellViewImpl *This = impl_from_IDropTarget(iface);
 
-	return E_NOTIMPL;
+    IDropTarget_DragLeave(This->pCurDropTarget);
+
+    IDropTarget_Release(This->pCurDropTarget);
+    IDataObject_Release(This->pCurDataObject);
+    This->pCurDataObject = NULL;
+    This->pCurDropTarget = NULL;
+    This->iDragOverItem = 0;
+     
+    start_stop_timer(This, IDT_LEFT,  FALSE);
+    start_stop_timer(This, IDT_RIGHT, FALSE);
+    start_stop_timer(This, IDT_UP,    FALSE);
+    start_stop_timer(This, IDT_DOWN,  FALSE);
+   
+    return S_OK;
 }
 
-static HRESULT WINAPI ISVDropTarget_Drop(
-	IDropTarget	*iface,
-	IDataObject*	pDataObject,
-	DWORD		grfKeyState,
-	POINTL		pt,
-	DWORD		*pdwEffect)
+static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataObject, 
+    DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
 {
-	IShellViewImpl *This = impl_from_IDropTarget(iface);
+    IShellViewImpl *This = impl_from_IDropTarget(iface);
 
-	FIXME("Stub: This=%p\n",This);
+    IDropTarget_Drop(This->pCurDropTarget, pDataObject, grfKeyState, pt, pdwEffect);
 
-	return E_NOTIMPL;
+    IDropTarget_Release(This->pCurDropTarget);
+    IDataObject_Release(This->pCurDataObject);
+    This->pCurDataObject = NULL;
+    This->pCurDropTarget = NULL;
+    This->iDragOverItem = 0;
+
+    start_stop_timer(This, IDT_LEFT,  FALSE);
+    start_stop_timer(This, IDT_RIGHT, FALSE);
+    start_stop_timer(This, IDT_UP,    FALSE);
+    start_stop_timer(This, IDT_DOWN,  FALSE);
+   
+    return S_OK;
 }
 
 static const IDropTargetVtbl dtvt =