mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[SHELL32] Correctly compare pidls for SHBrowseForFolder BFFM_SETEXPANDED (#7499)
_ILIsEqualSimple just does a memcmp and that does not work for all items. Should improve shell change notifications (CORE-13950).
This commit is contained in:
parent
81860b482a
commit
6d109254ab
9 changed files with 298 additions and 115 deletions
|
@ -4608,9 +4608,9 @@ HRESULT WINAPI CDefView::GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE CDefView::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
|
HRESULT STDMETHODCALLTYPE CDefView::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
|
||||||
{
|
{
|
||||||
if (IsEqualIID(guidService, SID_IShellBrowser))
|
if (IsEqualIID(guidService, SID_IShellBrowser) && m_pShellBrowser)
|
||||||
return m_pShellBrowser->QueryInterface(riid, ppvObject);
|
return m_pShellBrowser->QueryInterface(riid, ppvObject);
|
||||||
else if(IsEqualIID(guidService, SID_IFolderView))
|
else if (IsEqualIID(guidService, SID_IFolderView))
|
||||||
return QueryInterface(riid, ppvObject);
|
return QueryInterface(riid, ppvObject);
|
||||||
|
|
||||||
return E_NOINTERFACE;
|
return E_NOINTERFACE;
|
||||||
|
|
|
@ -11,11 +11,36 @@
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
|
||||||
#include <ui/layout.h> // Resizable window
|
#include <ui/layout.h> // Resizable window
|
||||||
|
#include <compat_undoc.h> // RosGetProcessEffectiveVersion
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||||
|
|
||||||
#define SHV_CHANGE_NOTIFY (WM_USER + 0x1111)
|
#define SHV_CHANGE_NOTIFY (WM_USER + 0x1111)
|
||||||
|
|
||||||
|
static LPITEMIDLIST
|
||||||
|
ILCloneToDepth(LPCITEMIDLIST pidlSrc, UINT depth)
|
||||||
|
{
|
||||||
|
SIZE_T cb = 0;
|
||||||
|
for (LPCITEMIDLIST pidl = pidlSrc; pidl && depth--; pidl = ILGetNext(pidl))
|
||||||
|
cb += pidl->mkid.cb;
|
||||||
|
|
||||||
|
LPITEMIDLIST pidlOut = (LPITEMIDLIST)SHAlloc(cb + sizeof(WORD));
|
||||||
|
if (pidlOut)
|
||||||
|
{
|
||||||
|
CopyMemory(pidlOut, pidlSrc, cb);
|
||||||
|
ZeroMemory(((BYTE*)pidlOut) + cb, sizeof(WORD));
|
||||||
|
}
|
||||||
|
return pidlOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INT
|
||||||
|
GetIconIndex(PCIDLIST_ABSOLUTE pidl, UINT uFlags)
|
||||||
|
{
|
||||||
|
SHFILEINFOW sfi;
|
||||||
|
SHGetFileInfoW((LPCWSTR)pidl, 0, &sfi, sizeof(sfi), uFlags);
|
||||||
|
return sfi.iIcon;
|
||||||
|
}
|
||||||
|
|
||||||
struct BrFolder
|
struct BrFolder
|
||||||
{
|
{
|
||||||
LPBROWSEINFOW lpBrowseInfo;
|
LPBROWSEINFOW lpBrowseInfo;
|
||||||
|
@ -145,12 +170,9 @@ BrFolder_InitTreeView(BrFolder *info)
|
||||||
{
|
{
|
||||||
HIMAGELIST hImageList;
|
HIMAGELIST hImageList;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
CComPtr<IShellFolder> lpsfParent;
|
|
||||||
CComPtr<IEnumIDList> pEnumChildren;
|
|
||||||
HTREEITEM hItem;
|
HTREEITEM hItem;
|
||||||
|
|
||||||
Shell_GetImageLists(NULL, &hImageList);
|
Shell_GetImageLists(NULL, &hImageList);
|
||||||
|
|
||||||
if (hImageList)
|
if (hImageList)
|
||||||
TreeView_SetImageList(info->hwndTreeView, hImageList, 0);
|
TreeView_SetImageList(info->hwndTreeView, hImageList, 0);
|
||||||
|
|
||||||
|
@ -171,54 +193,25 @@ BrFolder_InitTreeView(BrFolder *info)
|
||||||
ILRemoveLastID(pidlParent);
|
ILRemoveLastID(pidlParent);
|
||||||
PCIDLIST_RELATIVE pidlChild = ILFindLastID(pidlRoot);
|
PCIDLIST_RELATIVE pidlChild = ILFindLastID(pidlRoot);
|
||||||
|
|
||||||
if (_ILIsDesktop(pidlParent))
|
CComPtr<IShellFolder> lpsfParent;
|
||||||
{
|
hr = SHBindToObject(NULL, pidlParent, /*NULL, */ IID_PPV_ARG(IShellFolder, &lpsfParent));
|
||||||
hr = SHGetDesktopFolder(&lpsfParent);
|
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
if (FAILED_UNEXPECTEDLY(hr))
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CComPtr<IShellFolder> lpsfDesktop;
|
|
||||||
hr = SHGetDesktopFolder(&lpsfDesktop);
|
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
|
||||||
return;
|
|
||||||
|
|
||||||
hr = lpsfDesktop->BindToObject(pidlParent, NULL, IID_PPV_ARG(IShellFolder, &lpsfParent));
|
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TreeView_DeleteItem(info->hwndTreeView, TVI_ROOT);
|
TreeView_DeleteItem(info->hwndTreeView, TVI_ROOT);
|
||||||
hItem = BrFolder_InsertItem(info, lpsfParent, pidlChild, pidlParent, TVI_ROOT);
|
hItem = BrFolder_InsertItem(info, lpsfParent, pidlChild, pidlParent, TVI_ROOT);
|
||||||
TreeView_Expand(info->hwndTreeView, hItem, TVE_EXPAND);
|
TreeView_Expand(info->hwndTreeView, hItem, TVE_EXPAND);
|
||||||
}
|
}
|
||||||
|
|
||||||
static INT
|
|
||||||
BrFolder_GetIcon(PCIDLIST_ABSOLUTE pidl, UINT uFlags)
|
|
||||||
{
|
|
||||||
SHFILEINFOW sfi;
|
|
||||||
SHGetFileInfoW((LPCWSTR)pidl, 0, &sfi, sizeof(sfi), uFlags);
|
|
||||||
return sfi.iIcon;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
BrFolder_GetIconPair(PCIDLIST_ABSOLUTE pidl, LPTVITEMW pItem)
|
BrFolder_GetIconPair(PCIDLIST_ABSOLUTE pidl, LPTVITEMW pItem)
|
||||||
{
|
{
|
||||||
DWORD flags;
|
static const ITEMIDLIST idlDesktop = { };
|
||||||
|
|
||||||
CComHeapPtr<ITEMIDLIST_ABSOLUTE> pidlDesktop;
|
|
||||||
if (!pidl)
|
if (!pidl)
|
||||||
{
|
pidl = &idlDesktop;
|
||||||
pidlDesktop.Attach(_ILCreateDesktop());
|
DWORD flags = SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON;
|
||||||
pidl = pidlDesktop;
|
pItem->iImage = GetIconIndex(pidl, flags);
|
||||||
}
|
pItem->iSelectedImage = GetIconIndex(pidl, flags | SHGFI_OPENICON);
|
||||||
|
|
||||||
flags = SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON;
|
|
||||||
pItem->iImage = BrFolder_GetIcon(pidl, flags);
|
|
||||||
|
|
||||||
flags = SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_OPENICON;
|
|
||||||
pItem->iSelectedImage = BrFolder_GetIcon(pidl, flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
@ -766,6 +759,19 @@ BrFolder_OnInitDialog(HWND hWnd, BrFolder *info)
|
||||||
SHCNE_ALLEVENTS,
|
SHCNE_ALLEVENTS,
|
||||||
SHV_CHANGE_NOTIFY, 1, &ntreg);
|
SHV_CHANGE_NOTIFY, 1, &ntreg);
|
||||||
|
|
||||||
|
if (!lpBrowseInfo->pidlRoot)
|
||||||
|
{
|
||||||
|
UINT csidl = (lpBrowseInfo->ulFlags & BIF_NEWDIALOGSTYLE) ? CSIDL_PERSONAL : CSIDL_DRIVES;
|
||||||
|
LPITEMIDLIST pidl = SHCloneSpecialIDList(NULL, csidl, TRUE);
|
||||||
|
if (pidl)
|
||||||
|
{
|
||||||
|
SendMessageW(info->hWnd, BFFM_SETSELECTION, FALSE, (LPARAM)pidl);
|
||||||
|
if (csidl == CSIDL_DRIVES)
|
||||||
|
SendMessageW(info->hWnd, BFFM_SETEXPANDED, FALSE, (LPARAM)pidl);
|
||||||
|
ILFree(pidl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BrFolder_Callback(info->lpBrowseInfo, hWnd, BFFM_INITIALIZED, 0);
|
BrFolder_Callback(info->lpBrowseInfo, hWnd, BFFM_INITIALIZED, 0);
|
||||||
|
|
||||||
SHAutoComplete(GetDlgItem(hWnd, IDC_BROWSE_FOR_FOLDER_FOLDER_TEXT),
|
SHAutoComplete(GetDlgItem(hWnd, IDC_BROWSE_FOR_FOLDER_FOLDER_TEXT),
|
||||||
|
@ -985,8 +991,9 @@ BrFolder_OnContextMenu(BrFolder &info, LPARAM lParam)
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL
|
static BOOL
|
||||||
BrFolder_OnSetExpandedPidl(BrFolder *info, LPITEMIDLIST pidlSelection, HTREEITEM *phItem)
|
BrFolder_ExpandToPidl(BrFolder *info, LPITEMIDLIST pidlSelection, HTREEITEM *phItem)
|
||||||
{
|
{
|
||||||
|
LPITEMIDLIST pidlCurrent = pidlSelection;
|
||||||
if (_ILIsDesktop(pidlSelection))
|
if (_ILIsDesktop(pidlSelection))
|
||||||
{
|
{
|
||||||
if (phItem)
|
if (phItem)
|
||||||
|
@ -994,24 +1001,6 @@ BrFolder_OnSetExpandedPidl(BrFolder *info, LPITEMIDLIST pidlSelection, HTREEITEM
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move pidlCurrent behind the SHITEMIDs in pidlSelection, which are the root of
|
|
||||||
// the sub-tree currently displayed.
|
|
||||||
PCIDLIST_ABSOLUTE pidlRoot = info->lpBrowseInfo->pidlRoot;
|
|
||||||
LPITEMIDLIST pidlCurrent = pidlSelection;
|
|
||||||
while (!_ILIsEmpty(pidlRoot) && _ILIsEqualSimple(pidlRoot, pidlCurrent))
|
|
||||||
{
|
|
||||||
pidlRoot = ILGetNext(pidlRoot);
|
|
||||||
pidlCurrent = ILGetNext(pidlCurrent);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The given ID List is not part of the SHBrowseForFolder's current sub-tree.
|
|
||||||
if (!_ILIsEmpty(pidlRoot))
|
|
||||||
{
|
|
||||||
if (phItem)
|
|
||||||
*phItem = NULL;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize item to point to the first child of the root folder.
|
// Initialize item to point to the first child of the root folder.
|
||||||
TVITEMEXW item = { TVIF_PARAM };
|
TVITEMEXW item = { TVIF_PARAM };
|
||||||
item.hItem = TreeView_GetRoot(info->hwndTreeView);
|
item.hItem = TreeView_GetRoot(info->hwndTreeView);
|
||||||
|
@ -1019,18 +1008,28 @@ BrFolder_OnSetExpandedPidl(BrFolder *info, LPITEMIDLIST pidlSelection, HTREEITEM
|
||||||
item.hItem = TreeView_GetChild(info->hwndTreeView, item.hItem);
|
item.hItem = TreeView_GetChild(info->hwndTreeView, item.hItem);
|
||||||
|
|
||||||
// Walk the tree along the nodes corresponding to the remaining ITEMIDLIST
|
// Walk the tree along the nodes corresponding to the remaining ITEMIDLIST
|
||||||
while (item.hItem && !_ILIsEmpty(pidlCurrent))
|
UINT depth = _ILGetDepth(info->lpBrowseInfo->pidlRoot);
|
||||||
|
while (item.hItem && pidlCurrent)
|
||||||
{
|
{
|
||||||
|
LPITEMIDLIST pidlNeedle = ILCloneToDepth(pidlSelection, ++depth);
|
||||||
|
if (_ILIsEmpty(pidlNeedle))
|
||||||
|
{
|
||||||
|
ILFree(pidlNeedle);
|
||||||
|
item.hItem = NULL; // Failure
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
next:
|
||||||
TreeView_GetItem(info->hwndTreeView, &item);
|
TreeView_GetItem(info->hwndTreeView, &item);
|
||||||
BrItemData *pItemData = (BrItemData *)item.lParam;
|
const BrItemData *pItemData = (BrItemData *)item.lParam;
|
||||||
|
if (ILIsEqual(pItemData->pidlFull, pidlNeedle))
|
||||||
if (_ILIsEqualSimple(pItemData->pidlChild, pidlCurrent))
|
|
||||||
{
|
{
|
||||||
pidlCurrent = ILGetNext(pidlCurrent);
|
BOOL done = _ILGetDepth(pidlSelection) == _ILGetDepth(pidlNeedle);
|
||||||
if (!_ILIsEmpty(pidlCurrent))
|
if (done)
|
||||||
|
{
|
||||||
|
pidlCurrent = NULL; // Success
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// Only expand current node and move on to its first child,
|
|
||||||
// if we didn't already reach the last SHITEMID
|
|
||||||
TreeView_Expand(info->hwndTreeView, item.hItem, TVE_EXPAND);
|
TreeView_Expand(info->hwndTreeView, item.hItem, TVE_EXPAND);
|
||||||
item.hItem = TreeView_GetChild(info->hwndTreeView, item.hItem);
|
item.hItem = TreeView_GetChild(info->hwndTreeView, item.hItem);
|
||||||
}
|
}
|
||||||
|
@ -1038,7 +1037,10 @@ BrFolder_OnSetExpandedPidl(BrFolder *info, LPITEMIDLIST pidlSelection, HTREEITEM
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
item.hItem = TreeView_GetNextSibling(info->hwndTreeView, item.hItem);
|
item.hItem = TreeView_GetNextSibling(info->hwndTreeView, item.hItem);
|
||||||
|
if (item.hItem)
|
||||||
|
goto next;
|
||||||
}
|
}
|
||||||
|
ILFree(pidlNeedle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phItem)
|
if (phItem)
|
||||||
|
@ -1048,19 +1050,26 @@ BrFolder_OnSetExpandedPidl(BrFolder *info, LPITEMIDLIST pidlSelection, HTREEITEM
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL
|
static BOOL
|
||||||
BrFolder_OnSetExpandedString(BrFolder *info, LPWSTR pszString, HTREEITEM *phItem)
|
BrFolder_ExpandToString(BrFolder *info, LPWSTR pszString, HTREEITEM *phItem)
|
||||||
{
|
{
|
||||||
CComPtr<IShellFolder> psfDesktop;
|
|
||||||
HRESULT hr = SHGetDesktopFolder(&psfDesktop);
|
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
CComHeapPtr<ITEMIDLIST_ABSOLUTE> pidlSelection;
|
CComHeapPtr<ITEMIDLIST_ABSOLUTE> pidlSelection;
|
||||||
hr = psfDesktop->ParseDisplayName(NULL, NULL, pszString, NULL, &pidlSelection, NULL);
|
HRESULT hr = SHParseDisplayName(pszString, NULL, &pidlSelection, 0, NULL);
|
||||||
if (FAILED_UNEXPECTEDLY(hr))
|
return SUCCEEDED(hr) && BrFolder_ExpandToPidl(info, pidlSelection, phItem);
|
||||||
return FALSE;
|
}
|
||||||
|
|
||||||
return BrFolder_OnSetExpandedPidl(info, pidlSelection, phItem);
|
static BOOL
|
||||||
|
BrFolder_OnSetExpanded(BrFolder *info, LPITEMIDLIST pidlSelection, LPWSTR pszString)
|
||||||
|
{
|
||||||
|
HTREEITEM hItem;
|
||||||
|
BOOL ret;
|
||||||
|
if (pszString)
|
||||||
|
ret = BrFolder_ExpandToString(info, pszString, &hItem);
|
||||||
|
else
|
||||||
|
ret = BrFolder_ExpandToPidl(info, pidlSelection, &hItem);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
TreeView_Expand(info->hwndTreeView, hItem, TVE_EXPAND);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL
|
static BOOL
|
||||||
|
@ -1070,7 +1079,7 @@ BrFolder_OnSetSelectionPidl(BrFolder *info, LPITEMIDLIST pidlSelection)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
HTREEITEM hItem;
|
HTREEITEM hItem;
|
||||||
BOOL ret = BrFolder_OnSetExpandedPidl(info, pidlSelection, &hItem);
|
BOOL ret = BrFolder_ExpandToPidl(info, pidlSelection, &hItem);
|
||||||
if (ret)
|
if (ret)
|
||||||
TreeView_SelectItem(info->hwndTreeView, hItem);
|
TreeView_SelectItem(info->hwndTreeView, hItem);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1083,7 +1092,7 @@ BrFolder_OnSetSelectionW(BrFolder *info, LPWSTR pszSelection)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
HTREEITEM hItem;
|
HTREEITEM hItem;
|
||||||
BOOL ret = BrFolder_OnSetExpandedString(info, pszSelection, &hItem);
|
BOOL ret = BrFolder_ExpandToString(info, pszSelection, &hItem);
|
||||||
if (ret)
|
if (ret)
|
||||||
TreeView_SelectItem(info->hwndTreeView, hItem);
|
TreeView_SelectItem(info->hwndTreeView, hItem);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1304,9 +1313,9 @@ BrFolderDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
|
|
||||||
case BFFM_SETEXPANDED: // Unicode only
|
case BFFM_SETEXPANDED: // Unicode only
|
||||||
if (wParam) // String
|
if (wParam) // String
|
||||||
return BrFolder_OnSetExpandedString(info, (LPWSTR)lParam, NULL);
|
return BrFolder_OnSetExpanded(info, NULL, (LPWSTR)lParam);
|
||||||
else // PIDL
|
else // PIDL
|
||||||
return BrFolder_OnSetExpandedPidl(info, (LPITEMIDLIST)lParam, NULL);
|
return BrFolder_OnSetExpanded(info, (LPITEMIDLIST)lParam, NULL);
|
||||||
|
|
||||||
case SHV_CHANGE_NOTIFY:
|
case SHV_CHANGE_NOTIFY:
|
||||||
BrFolder_OnChange(info, wParam, lParam);
|
BrFolder_OnChange(info, wParam, lParam);
|
||||||
|
@ -1362,16 +1371,23 @@ SHBrowseForFolderW(LPBROWSEINFOW lpbi)
|
||||||
{
|
{
|
||||||
TRACE("%p\n", lpbi);
|
TRACE("%p\n", lpbi);
|
||||||
|
|
||||||
|
// MSDN says the caller must initialize COM. We do it anyway in case the caller forgot.
|
||||||
|
COleInit OleInit;
|
||||||
BrFolder info = { lpbi };
|
BrFolder info = { lpbi };
|
||||||
|
|
||||||
HRESULT hr = OleInitialize(NULL);
|
|
||||||
|
|
||||||
INT id = ((lpbi->ulFlags & BIF_USENEWUI) ? IDD_BROWSE_FOR_FOLDER_NEW : IDD_BROWSE_FOR_FOLDER);
|
INT id = ((lpbi->ulFlags & BIF_USENEWUI) ? IDD_BROWSE_FOR_FOLDER_NEW : IDD_BROWSE_FOR_FOLDER);
|
||||||
INT_PTR ret = DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(id), lpbi->hwndOwner,
|
INT_PTR ret = DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(id), lpbi->hwndOwner,
|
||||||
BrFolderDlgProc, (LPARAM)&info);
|
BrFolderDlgProc, (LPARAM)&info);
|
||||||
if (SUCCEEDED(hr))
|
if (ret == IDOK && !(lpbi->ulFlags & BIF_NOTRANSLATETARGETS) &&
|
||||||
OleUninitialize();
|
RosGetProcessEffectiveVersion() >= _WIN32_WINNT_WINXP)
|
||||||
|
{
|
||||||
|
PIDLIST_ABSOLUTE pidlTarget;
|
||||||
|
if (SHELL_GetIDListTarget(info.pidlRet, &pidlTarget) == S_OK)
|
||||||
|
{
|
||||||
|
ILFree(info.pidlRet);
|
||||||
|
info.pidlRet = pidlTarget;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (ret != IDOK)
|
if (ret != IDOK)
|
||||||
{
|
{
|
||||||
ILFree(info.pidlRet);
|
ILFree(info.pidlRet);
|
||||||
|
|
|
@ -20,13 +20,20 @@ static LPCWSTR GetItemFileName(PCUITEMID_CHILD pidl, LPWSTR Buf, UINT cchMax)
|
||||||
if (pDataW)
|
if (pDataW)
|
||||||
return pDataW->wszName;
|
return pDataW->wszName;
|
||||||
LPPIDLDATA pdata = _ILGetDataPointer(pidl);
|
LPPIDLDATA pdata = _ILGetDataPointer(pidl);
|
||||||
if ((pdata->type & PT_VALUEW) == PT_VALUEW)
|
if (_ILGetFSType(pidl) & PT_FS_UNICODE_FLAG)
|
||||||
return (LPWSTR)pdata->u.file.szNames;
|
return (LPWSTR)pdata->u.file.szNames;
|
||||||
if (_ILSimpleGetTextW(pidl, Buf, cchMax))
|
if (_ILSimpleGetTextW(pidl, Buf, cchMax))
|
||||||
return Buf;
|
return Buf;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL IsRealItem(const ITEMIDLIST &idl)
|
||||||
|
{
|
||||||
|
// PIDLs created with SHSimpleIDListFromPath contain no data, otherwise, the item is "real"
|
||||||
|
FileStruct &fsitem = ((PIDLDATA*)idl.mkid.abID)->u.file;
|
||||||
|
return fsitem.dwFileSize | fsitem.uFileDate;
|
||||||
|
}
|
||||||
|
|
||||||
static HKEY OpenKeyFromFileType(LPCWSTR pExtension, LPCWSTR KeyName)
|
static HKEY OpenKeyFromFileType(LPCWSTR pExtension, LPCWSTR KeyName)
|
||||||
{
|
{
|
||||||
HKEY hkey;
|
HKEY hkey;
|
||||||
|
@ -1079,6 +1086,9 @@ HRESULT WINAPI CFSFolder::CompareIDs(LPARAM lParam,
|
||||||
/* When sorting between a File and a Folder, the Folder gets sorted first */
|
/* When sorting between a File and a Folder, the Folder gets sorted first */
|
||||||
if (bIsFolder1 != bIsFolder2)
|
if (bIsFolder1 != bIsFolder2)
|
||||||
{
|
{
|
||||||
|
// ...but only if neither of them were generated by SHSimpleIDListFromPath
|
||||||
|
// because in that case we cannot tell if it's a file or a folder.
|
||||||
|
if (IsRealItem(*pidl1) && IsRealItem(*pidl2))
|
||||||
return MAKE_COMPARE_HRESULT(bIsFolder1 ? -1 : 1);
|
return MAKE_COMPARE_HRESULT(bIsFolder1 ? -1 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -219,6 +219,7 @@ SHBindToObjectEx(
|
||||||
|
|
||||||
DWORD
|
DWORD
|
||||||
SHGetAttributes(_In_ IShellFolder *psf, _In_ LPCITEMIDLIST pidl, _In_ DWORD dwAttributes);
|
SHGetAttributes(_In_ IShellFolder *psf, _In_ LPCITEMIDLIST pidl, _In_ DWORD dwAttributes);
|
||||||
|
HRESULT SHELL_GetIDListTarget(_In_ LPCITEMIDLIST pidl, _Out_ PIDLIST_ABSOLUTE *ppidl);
|
||||||
HRESULT SHCoInitializeAnyApartment(VOID);
|
HRESULT SHCoInitializeAnyApartment(VOID);
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
|
|
|
@ -1633,7 +1633,8 @@ static HRESULT delete_files(FILE_OPERATION *op, const FILE_LIST *flFrom)
|
||||||
BOOL bDelete;
|
BOOL bDelete;
|
||||||
if (TRASH_TrashFile(fileEntry->szFullPath))
|
if (TRASH_TrashFile(fileEntry->szFullPath))
|
||||||
{
|
{
|
||||||
SHChangeNotify(SHCNE_DELETE, SHCNF_PATHW, fileEntry->szFullPath, NULL);
|
UINT event = IsAttribFile(fileEntry->attributes) ? SHCNE_DELETE : SHCNE_RMDIR;
|
||||||
|
SHChangeNotify(event, SHCNF_PATHW, fileEntry->szFullPath, NULL);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1652,9 +1653,7 @@ static HRESULT delete_files(FILE_OPERATION *op, const FILE_LIST *flFrom)
|
||||||
|
|
||||||
/* delete the file or directory */
|
/* delete the file or directory */
|
||||||
if (IsAttribFile(fileEntry->attributes))
|
if (IsAttribFile(fileEntry->attributes))
|
||||||
{
|
|
||||||
bPathExists = (ERROR_SUCCESS == SHNotifyDeleteFileW(op, fileEntry->szFullPath));
|
bPathExists = (ERROR_SUCCESS == SHNotifyDeleteFileW(op, fileEntry->szFullPath));
|
||||||
}
|
|
||||||
else
|
else
|
||||||
bPathExists = SHELL_DeleteDirectoryW(op, fileEntry->szFullPath, FALSE);
|
bPathExists = SHELL_DeleteDirectoryW(op, fileEntry->szFullPath, FALSE);
|
||||||
|
|
||||||
|
|
|
@ -277,6 +277,18 @@ SHGetAttributes(_In_ IShellFolder *psf, _In_ LPCITEMIDLIST pidl, _In_ DWORD dwAt
|
||||||
return dwAttributes;
|
return dwAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT SHELL_GetIDListTarget(_In_ LPCITEMIDLIST pidl, _Out_ PIDLIST_ABSOLUTE *ppidl)
|
||||||
|
{
|
||||||
|
IShellLink *pSL;
|
||||||
|
HRESULT hr = SHBindToObject(NULL, pidl, IID_PPV_ARG(IShellLink, &pSL));
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = pSL->GetIDList(ppidl); // Note: Returns S_FALSE if no target pidl
|
||||||
|
pSL->Release();
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT SHCoInitializeAnyApartment(VOID)
|
HRESULT SHCoInitializeAnyApartment(VOID)
|
||||||
{
|
{
|
||||||
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
|
||||||
|
|
|
@ -485,6 +485,37 @@ LPITEMIDLIST WINAPI ILGlobalClone(LPCITEMIDLIST pidl)
|
||||||
return newpidl;
|
return newpidl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
static inline LPITEMIDLIST _ILUnsafeNext(LPCITEMIDLIST pidl)
|
||||||
|
{
|
||||||
|
return (LPITEMIDLIST)(((BYTE*)pidl) + pidl->mkid.cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT _ILGetDepth(LPCITEMIDLIST pidl)
|
||||||
|
{
|
||||||
|
for (UINT i = 0;; ++i)
|
||||||
|
{
|
||||||
|
if (!pidl || !pidl->mkid.cb)
|
||||||
|
return i;
|
||||||
|
pidl = _ILUnsafeNext(pidl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL _ILMemCmpEqualIDList(LPCITEMIDLIST p1, LPCITEMIDLIST p2)
|
||||||
|
{
|
||||||
|
for (;; p1 = _ILUnsafeNext(p1), p2 = _ILUnsafeNext(p2))
|
||||||
|
{
|
||||||
|
DWORD cb1 = p1 ? p1->mkid.cb : 0x80000000; /* Empty != NULL */
|
||||||
|
DWORD cb2 = p2 ? p2->mkid.cb : 0x80000000;
|
||||||
|
if (cb1 != cb2)
|
||||||
|
return FALSE;
|
||||||
|
if (LOWORD(cb1) == 0)
|
||||||
|
return cb1 == cb2;
|
||||||
|
if (memcmp(p1, p2, cb1))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else /* __REACTOS__ */
|
||||||
BOOL _ILHACKCompareSimpleIds(LPCITEMIDLIST pidltemp1, LPCITEMIDLIST pidltemp2)
|
BOOL _ILHACKCompareSimpleIds(LPCITEMIDLIST pidltemp1, LPCITEMIDLIST pidltemp2)
|
||||||
{
|
{
|
||||||
LPPIDLDATA pdata1 = _ILGetDataPointer(pidltemp1);
|
LPPIDLDATA pdata1 = _ILGetDataPointer(pidltemp1);
|
||||||
|
@ -540,6 +571,7 @@ BOOL _ILHACKCompareSimpleIds(LPCITEMIDLIST pidltemp1, LPCITEMIDLIST pidltemp2)
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
#endif /* __REACTOS__ */
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* ILIsEqual [SHELL32.21]
|
* ILIsEqual [SHELL32.21]
|
||||||
|
@ -552,6 +584,21 @@ BOOL WINAPI ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
|
||||||
|
|
||||||
TRACE("pidl1=%p pidl2=%p\n",pidl1, pidl2);
|
TRACE("pidl1=%p pidl2=%p\n",pidl1, pidl2);
|
||||||
|
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
IShellFolder *psfDesktop;
|
||||||
|
UINT depth1;
|
||||||
|
|
||||||
|
if (pidl1 == pidl2 || _ILMemCmpEqualIDList(pidltemp1, pidltemp2))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
depth1 = _ILGetDepth(pidl1);
|
||||||
|
if (depth1 && depth1 == _ILGetDepth(pidl2) && SUCCEEDED(SHGetDesktopFolder(&psfDesktop)))
|
||||||
|
{
|
||||||
|
HRESULT hr = IShellFolder_CompareIDs(psfDesktop, SHCIDS_CANONICALONLY, pidl1, pidl2);
|
||||||
|
IShellFolder_Release(psfDesktop);
|
||||||
|
return hr == 0;
|
||||||
|
}
|
||||||
|
#else /* __REACTOS__ */
|
||||||
/*
|
/*
|
||||||
* Explorer reads from registry directly (StreamMRU),
|
* Explorer reads from registry directly (StreamMRU),
|
||||||
* so we can only check here
|
* so we can only check here
|
||||||
|
@ -582,10 +629,47 @@ BOOL WINAPI ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
|
||||||
|
|
||||||
if (!pidltemp1->mkid.cb && !pidltemp2->mkid.cb)
|
if (!pidltemp1->mkid.cb && !pidltemp2->mkid.cb)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
#endif /* __REACTOS__ */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LPCITEMIDLIST _ILIsParentEx(LPCITEMIDLIST pidlParent, LPCITEMIDLIST pidlChild, BOOL bImmediate)
|
||||||
|
{
|
||||||
|
LPCITEMIDLIST pParentRoot = pidlParent, pChildRoot = pidlChild, pResult = NULL;
|
||||||
|
LPITEMIDLIST pidl;
|
||||||
|
SIZE_T cb = 0;
|
||||||
|
|
||||||
|
if (!pidlParent || !pidlChild)
|
||||||
|
return pResult;
|
||||||
|
|
||||||
|
while (pidlParent->mkid.cb)
|
||||||
|
{
|
||||||
|
cb += pidlChild->mkid.cb;
|
||||||
|
if (!pidlChild->mkid.cb)
|
||||||
|
{
|
||||||
|
if (pidlParent->mkid.cb)
|
||||||
|
return pResult; /* The child is shorter than the parent */
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pidlChild = _ILUnsafeNext(pidlChild);
|
||||||
|
pidlParent = _ILUnsafeNext(pidlParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bImmediate && (!pidlChild->mkid.cb || _ILUnsafeNext(pidlChild)->mkid.cb))
|
||||||
|
return pResult; /* Same as parent or a deeper grandchild */
|
||||||
|
|
||||||
|
if ((pidl = SHAlloc(cb + sizeof(WORD))) != NULL)
|
||||||
|
{
|
||||||
|
CopyMemory(pidl, pChildRoot, cb);
|
||||||
|
ZeroMemory((BYTE*)pidl + cb, sizeof(WORD));
|
||||||
|
if (ILIsEqual(pParentRoot, pidl))
|
||||||
|
pResult = pidlChild;
|
||||||
|
ILFree(pidl);
|
||||||
|
}
|
||||||
|
return pResult;
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* ILIsParent [SHELL32.23]
|
* ILIsParent [SHELL32.23]
|
||||||
*
|
*
|
||||||
|
@ -615,6 +699,9 @@ BOOL WINAPI ILIsParent(LPCITEMIDLIST pidlParent, LPCITEMIDLIST pidlChild, BOOL b
|
||||||
|
|
||||||
TRACE("%p %p %x\n", pidlParent, pidlChild, bImmediate);
|
TRACE("%p %p %x\n", pidlParent, pidlChild, bImmediate);
|
||||||
|
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
return _ILIsParentEx(pParent, pChild, bImmediate) != NULL;
|
||||||
|
#else /* __REACTOS__ */
|
||||||
if (!pParent || !pChild)
|
if (!pParent || !pChild)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -636,6 +723,7 @@ BOOL WINAPI ILIsParent(LPCITEMIDLIST pidlParent, LPCITEMIDLIST pidlChild, BOOL b
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
#endif /* __REACTOS__ */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
|
@ -659,6 +747,13 @@ BOOL WINAPI ILIsParent(LPCITEMIDLIST pidlParent, LPCITEMIDLIST pidlChild, BOOL b
|
||||||
*/
|
*/
|
||||||
PUIDLIST_RELATIVE WINAPI ILFindChild(PIDLIST_ABSOLUTE pidl1, PCIDLIST_ABSOLUTE pidl2)
|
PUIDLIST_RELATIVE WINAPI ILFindChild(PIDLIST_ABSOLUTE pidl1, PCIDLIST_ABSOLUTE pidl2)
|
||||||
{
|
{
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
TRACE("pidl1=%p pidl2=%p\n", pidl1, pidl2);
|
||||||
|
|
||||||
|
if (_ILIsDesktop(pidl1))
|
||||||
|
return (PUIDLIST_RELATIVE)pidl2;
|
||||||
|
return (PUIDLIST_RELATIVE)_ILIsParentEx(pidl1, pidl2, FALSE);
|
||||||
|
#else /* __REACTOS__ */
|
||||||
LPCITEMIDLIST pidltemp1 = pidl1;
|
LPCITEMIDLIST pidltemp1 = pidl1;
|
||||||
LPCITEMIDLIST pidltemp2 = pidl2;
|
LPCITEMIDLIST pidltemp2 = pidl2;
|
||||||
LPCITEMIDLIST ret=NULL;
|
LPCITEMIDLIST ret=NULL;
|
||||||
|
@ -694,6 +789,7 @@ PUIDLIST_RELATIVE WINAPI ILFindChild(PIDLIST_ABSOLUTE pidl1, PCIDLIST_ABSOLUTE p
|
||||||
}
|
}
|
||||||
TRACE_(shell)("--- %p\n", ret);
|
TRACE_(shell)("--- %p\n", ret);
|
||||||
return (PUIDLIST_RELATIVE)ret; /* pidl 1 is shorter */
|
return (PUIDLIST_RELATIVE)ret; /* pidl 1 is shorter */
|
||||||
|
#endif /* __REACTOS__ */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
|
|
|
@ -105,8 +105,9 @@ extern "C" {
|
||||||
#define PT_SHARE 0xc3
|
#define PT_SHARE 0xc3
|
||||||
|
|
||||||
#ifdef __REACTOS__
|
#ifdef __REACTOS__
|
||||||
|
#define PT_FOLDERTYPEMASK 0x70
|
||||||
#define PT_DESKTOP_REGITEM 0x1F // => SHDID_ROOT_REGITEM
|
#define PT_DESKTOP_REGITEM 0x1F // => SHDID_ROOT_REGITEM
|
||||||
#define PT_COMPUTER_REGITEM 0x2E // => SHDID_COMPUTER_OTHER
|
#define PT_COMPUTER_REGITEM 0x2E // => SHDID_COMPUTER_?
|
||||||
#define PT_FS 0x30 // Win95 SHSimpleIDListFromPath
|
#define PT_FS 0x30 // Win95 SHSimpleIDListFromPath
|
||||||
#define PT_FS_FOLDER_FLAG 0x01
|
#define PT_FS_FOLDER_FLAG 0x01
|
||||||
#define PT_FS_FILE_FLAG 0x02
|
#define PT_FS_FILE_FLAG 0x02
|
||||||
|
@ -116,6 +117,17 @@ extern "C" {
|
||||||
#define PT_CONTROLS_NEWREGITEM 0x71
|
#define PT_CONTROLS_NEWREGITEM 0x71
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline BYTE _ILGetType(LPCITEMIDLIST pidl)
|
||||||
|
{
|
||||||
|
return pidl && pidl->mkid.cb >= 3 ? pidl->mkid.abID[0] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline BYTE _ILGetFSType(LPCITEMIDLIST pidl)
|
||||||
|
{
|
||||||
|
const BYTE type = _ILGetType(pidl);
|
||||||
|
return (type & PT_FOLDERTYPEMASK) == PT_FS ? type : 0;
|
||||||
|
}
|
||||||
|
|
||||||
#include "pshpack1.h"
|
#include "pshpack1.h"
|
||||||
typedef BYTE PIDLTYPE;
|
typedef BYTE PIDLTYPE;
|
||||||
|
|
||||||
|
@ -257,14 +269,8 @@ BOOL _ILIsValue (LPCITEMIDLIST pidl) DECLSPEC_HIDDEN;
|
||||||
BOOL _ILIsSpecialFolder (LPCITEMIDLIST pidl) DECLSPEC_HIDDEN;
|
BOOL _ILIsSpecialFolder (LPCITEMIDLIST pidl) DECLSPEC_HIDDEN;
|
||||||
BOOL _ILIsPidlSimple (LPCITEMIDLIST pidl) DECLSPEC_HIDDEN;
|
BOOL _ILIsPidlSimple (LPCITEMIDLIST pidl) DECLSPEC_HIDDEN;
|
||||||
BOOL _ILIsCPanelStruct (LPCITEMIDLIST pidl) DECLSPEC_HIDDEN;
|
BOOL _ILIsCPanelStruct (LPCITEMIDLIST pidl) DECLSPEC_HIDDEN;
|
||||||
static inline
|
static inline BOOL _ILIsEmpty(LPCITEMIDLIST pidl) { return _ILIsDesktop(pidl); }
|
||||||
BOOL _ILIsEqualSimple (LPCITEMIDLIST pidlA, LPCITEMIDLIST pidlB)
|
UINT _ILGetDepth(LPCITEMIDLIST pidl);
|
||||||
{
|
|
||||||
return (pidlA->mkid.cb > 0 && !memcmp(pidlA, pidlB, pidlA->mkid.cb)) ||
|
|
||||||
(!pidlA->mkid.cb && !pidlB->mkid.cb);
|
|
||||||
}
|
|
||||||
static inline
|
|
||||||
BOOL _ILIsEmpty (LPCITEMIDLIST pidl) { return _ILIsDesktop(pidl); }
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* simple pidls
|
* simple pidls
|
||||||
|
|
|
@ -597,21 +597,19 @@ void DumpIdList(LPCITEMIDLIST pcidl)
|
||||||
DbgPrint("End IDList Dump.\n");
|
DbgPrint("End IDList Dump.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CCoInit
|
template <HRESULT (WINAPI *InitFunc)(void*), void (WINAPI *UninitFunc)()>
|
||||||
|
struct CCoInitBase
|
||||||
{
|
{
|
||||||
CCoInit()
|
HRESULT hr;
|
||||||
{
|
CCoInitBase() : hr(InitFunc(NULL)) { }
|
||||||
hr = CoInitialize(NULL);
|
~CCoInitBase()
|
||||||
}
|
|
||||||
~CCoInit()
|
|
||||||
{
|
{
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
UninitFunc();
|
||||||
CoUninitialize();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
HRESULT hr;
|
|
||||||
};
|
};
|
||||||
|
typedef CCoInitBase<CoInitialize, CoUninitialize> CCoInit;
|
||||||
|
typedef CCoInitBase<OleInitialize, OleUninitialize> COleInit;
|
||||||
|
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
@ -828,5 +826,50 @@ struct SHELL_GetSettingImpl
|
||||||
#define SHELL_GetSetting(pss, ssf, field) ( SHGetSetSettings((pss), (ssf), FALSE), (pss)->field )
|
#define SHELL_GetSetting(pss, ssf, field) ( SHGetSetSettings((pss), (ssf), FALSE), (pss)->field )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline void DumpIdListOneLine(LPCITEMIDLIST pidl)
|
||||||
|
{
|
||||||
|
char buf[1024], *data, drive = 0;
|
||||||
|
for (UINT depth = 0, type; ; pidl = ILGetNext(pidl), ++depth)
|
||||||
|
{
|
||||||
|
if (!pidl || !pidl->mkid.cb)
|
||||||
|
{
|
||||||
|
if (!depth)
|
||||||
|
{
|
||||||
|
wsprintfA(buf, "%p [] (%s)\n", pidl, pidl ? "Empty/Desktop" : "NULL");
|
||||||
|
OutputDebugStringA(buf);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (!depth)
|
||||||
|
{
|
||||||
|
wsprintfA(buf, "%p", pidl);
|
||||||
|
OutputDebugStringA(buf);
|
||||||
|
}
|
||||||
|
type = pidl->mkid.abID[0] & 0x7f;
|
||||||
|
data = (char*)&pidl->mkid.abID[0];
|
||||||
|
if (depth == 0 && type == 0x1f && pidl->mkid.cb == 20 && *(UINT*)(&data[2]) == 0x20D04FE0)
|
||||||
|
{
|
||||||
|
wsprintfA(buf, " [%.2x ThisPC?]", type); /* "?" because we did not check the full GUID */
|
||||||
|
}
|
||||||
|
else if (depth == 1 && type >= 0x20 && type < 0x30 && type != 0x2E && pidl->mkid.cb > 4)
|
||||||
|
{
|
||||||
|
drive = data[1];
|
||||||
|
wsprintfA(buf, " [%.2x %c: %ub]", type, drive, pidl->mkid.cb);
|
||||||
|
}
|
||||||
|
else if (depth >= 2 && drive && (type & 0x70) == 0x30) /* PT_FS */
|
||||||
|
{
|
||||||
|
if (type & 4)
|
||||||
|
wsprintfA(buf, " [%.2x FS %.256ls %ub]", type, data + 12, pidl->mkid.cb);
|
||||||
|
else
|
||||||
|
wsprintfA(buf, " [%.2x FS %.256hs %ub]", type, data + 12, pidl->mkid.cb);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wsprintfA(buf, " [%.2x ? %ub]", type, pidl->mkid.cb);
|
||||||
|
}
|
||||||
|
OutputDebugStringA(buf);
|
||||||
|
}
|
||||||
|
OutputDebugStringA("\n");
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* __ROS_SHELL_UTILS_H */
|
#endif /* __ROS_SHELL_UTILS_H */
|
||||||
|
|
Loading…
Reference in a new issue