有关Shell编程:IMalloc::Free()在_MBCS下编译运行正常,在_UNICODE下失败

ChenLiuqing 2005-08-22 06:06:58
我现在是实现一个Shell Tree显示桌面为根的树状列表
typedef struct tagID
{
// Contains the LPIDL of the desktop
LPSHELLFOLDER lpsfParent;
// Contains the LPITEMIDLIST of the file / folder relatived
// to the parent folder
LPITEMIDLIST lpi;
// Contains the full LPITEMIDLIST of the file / folder relatived
// to the desktop
LPITEMIDLIST lpifq;
} TVITEMDATA, *LPTVITEMDATA;
用这个结构作为TREEITEM 的lParam
下面是几个相关的函数
// Get the subfolders of the current folder and display them
// Params:
// lpsf: the ISHELLFOLDER object of the folder
// lpifq
void CShellTreeCtrl::DisplaySubItems(LPSHELLFOLDER lpsf, LPITEMIDLIST lpifq, HTREEITEM hParent)
{
// the TV_ITEM struct used to insert item
TV_ITEM tvi;
// The TV_INSERTSTRUCT struct of the item to be inserted
TV_INSERTSTRUCT tvins;
// The previouse added item handle
HTREEITEM hPrevTreeItem = NULL;
// IEnumIDList interface point
LPENUMIDLIST lpe = NULL;
LPITEMIDLIST lpi = NULL, lpiTemp = NULL, lpidlThisItem = NULL;
LPTVITEMDATA lptvid = NULL;
LPMALLOC lpMalloc = NULL;
// ULONG ulFetched;
// Count
UINT uCount=0;
HRESULT hr;
TCHAR szBuff[MAX_PATH];
// The handle of the parent window
HWND hwnd = GetParent()->m_hWnd;

// Alloc shell memory
hr = SHGetMalloc( &lpMalloc );
if (FAILED(hr))
return;

// Get the IEnumIDList of the IShellFolder interface
hr = lpsf->EnumObjects(hwnd, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &lpe);

if (SUCCEEDED(hr))
{
while (S_OK == lpe->Next(1, &lpi, NULL))
{
// Attributes flag: is folder and if has sub folder
ULONG ulAttrs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_LINK;
lpsf->GetAttributesOf(1, (const struct _ITEMIDLIST **)&lpi, &ulAttrs);
// If the current item is directory
if (ulAttrs & SFGAO_FOLDER)
{
tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;

//if (ulAttrs & SFGAO_HASSUBFOLDER)
//{
// tvi.cChildren=1;
// tvi.mask |= TVIF_CHILDREN;
//}

// Alloc memory
lptvid = (LPTVITEMDATA)lpMalloc->Alloc(sizeof(TVITEMDATA));
if (!lptvid)
goto Done;

// Get the item name
if (!GetName(lpsf, lpi, SHGDN_NORMAL, szBuff))
goto Done;
tvi.pszText = szBuff;n
#ifdef DEBUG
TRACE( _T("Displaying %s\r\n"), szBuff );
#endif
// If the folder has sub folders / files,
// set corresponding Treectrl item attribute
if( (ulAttrs & SFGAO_HASSUBFOLDER) || HasGotSubEntries(lpsf, lpi) )
{
tvi.cChildren=1;
tvi.mask |= TVIF_CHILDREN;
}

tvi.cchTextMax = _MAX_PATH;
lpidlThisItem = ConcatPidls(lpifq, lpi);

//Copy ITEMIDLIST
lptvid->lpi = CopyITEMID(lpMalloc, lpi);

tvi.iImage = GetIconIndex(lpidlThisItem);

tvi.iSelectedImage = GetSelIconIndex(lpidlThisItem);
// Save the parent folder
lptvid->lpsfParent = lpsf;
lpsf->AddRef();

lptvid->lpifq = ConcatPidls(lpifq, lpi);

tvi.lParam = (LPARAM)lptvid;
// Insert a file / folder item to treectrl
tvins.item = tvi;
tvins.hInsertAfter = hPrevTreeItem;
tvins.hParent = hParent;
hPrevTreeItem = InsertItem(&tvins);
}
else
// Ignoure the shortcuts
if( !(SFGAO_LINK & ulAttrs) )
{
tvi.mask= TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;

// Alloc memory
lptvid = (LPTVITEMDATA)lpMalloc->Alloc(sizeof(TVITEMDATA));
if (!lptvid)
goto Done;

// Get the item name
if (!GetName(lpsf, lpi, SHGDN_NORMAL, szBuff))
goto Done;
///*
// If m_sFileFilter is not empty, do the estimate work
if( !m_sFileFilter.IsEmpty() )
{
if( !MatchFilters(szBuff) )
{
lpMalloc->Free(lpidlThisItem);
lpidlThisItem = 0;
continue;
}
}//*/
tvi.pszText = szBuff;
tvi.cchTextMax = MAX_PATH;
lpidlThisItem = ConcatPidls(lpifq, lpi);

//Copy ITEMIDLIST
lptvid->lpi = CopyITEMID(lpMalloc, lpi);

tvi.iImage = GetIconIndex(lpidlThisItem);
tvi.iSelectedImage = GetSelIconIndex(lpidlThisItem);
// Save the parent folder
lptvid->lpsfParent = lpsf;
lpsf->AddRef();

//lptvid->lpifq = ConcatPidls(lpifq, lpi);
lptvid->lpifq = lpidlThisItem;

tvi.lParam = (LPARAM)lptvid;
// Insert a file / folder item to TreeCtrl
tvins.item = tvi;
tvins.hInsertAfter = hPrevTreeItem;
tvins.hParent = hParent;
hPrevTreeItem = InsertItem(&tvins);
}
if( lpidlThisItem )
{
lpMalloc->Free( lpidlThisItem );
lpidlThisItem = 0;
}
}// End while
// Free memory.
if( lpi )
{
lpMalloc->Free(lpi);
lpi=0;
}
} // end if
// Do the clean up work
Done:
if (lpe)
lpe->Release();
if (lpi && lpMalloc)
lpMalloc->Free(lpi);
if (lpidlThisItem && lpMalloc)
lpMalloc->Free(lpidlThisItem);
if (lpMalloc)
lpMalloc->Release();
}
...全文
149 点赞 收藏 7
写回复
7 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
goodboyws 2005-08-23
内存越界了,估计就是楼上说的问题
回复
everandforever 2005-08-23

LPITEMIDLIST CShellTreeCtrl::ConcatPidls(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
中的
memcpy(((LPTSTR)pidlNew) + cb1, pidl2, cb2);
改成
memcpy(((BYTE*)pidlNew) + cb1, pidl2, cb2);
试试
回复
ChenLiuqing 2005-08-23
结贴,goodboyws大侠来晚一步,意思一下,呵呵
回复
ChenLiuqing 2005-08-23
花了半天终于把这个bug找出来了,本来是用的部分别人的代码,看来在没有吃透的情况下还是慎重的好。everandforever(Forever)说的是一个错误,非常感谢!另外一个是要把ITEMLIST结构的最后一位一定要写成0!
回复
ChenLiuqing 2005-08-22
这是错误信息
HEAP[ResourceFinder.exe]: Heap block at 00170848 modified at 0017087A past requested size of 2a
Unhandled exception at 0x7c901230 in ResourceFinder.exe: User breakpoint.
HEAP[ResourceFinder.exe]: Invalid Address specified to RtlFreeHeap( 00150000, 00170850 )
Unhandled exception at 0x7c901230 in ResourceFinder.exe: User breakpoint.
The program '[2952] ResourceFinder.exe: Native' has exited with code 0 (0x0).
回复
ChenLiuqing 2005-08-22
在用_MBCS编译运行的时候很正常,改为_UNICODE编译以后,在列举My Computer下面的磁盘项目时报错,break时显示停在
void CShellTreeCtrl::DisplaySubItems(LPSHELLFOLDER lpsf, LPITEMIDLIST lpifq, HTREEITEM hParent)
函数中的这一行,
lpMalloc->Free( lpidlThisItem );

请对Shell编程熟悉的大侠帮忙看看,100分相送,不够再加!
回复
ChenLiuqing 2005-08-22
LPITEMIDLIST CShellTreeCtrl::ConcatPidls(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
{
LPITEMIDLIST pidlNew;
UINT cb1;
UINT cb2;

if (pidl1) //May be NULL
cb1 = GetSize(pidl1) - sizeof(pidl1->mkid.cb);
else
cb1 = 0;

cb2 = GetSize(pidl2);

pidlNew = CreatePidl(cb1 + cb2);
if (pidlNew)
{
if (pidl1)
memcpy(pidlNew, pidl1, cb1);
memcpy(((LPTSTR)pidlNew) + cb1, pidl2, cb2);
}
return pidlNew;
}

LPITEMIDLIST CShellTreeCtrl::CopyITEMID(LPMALLOC lpMalloc, LPITEMIDLIST lpi)
{
LPITEMIDLIST lpiTemp;

lpiTemp=(LPITEMIDLIST)lpMalloc->Alloc( lpi->mkid.cb + sizeof(lpi->mkid.cb) );
CopyMemory((PVOID)lpiTemp, (CONST VOID *)lpi, lpi->mkid.cb + sizeof(lpi->mkid.cb));

return lpiTemp;
}

LPITEMIDLIST CShellTreeCtrl::CreatePidl(UINT cbSize)
{
LPMALLOC lpMalloc;
HRESULT hr;
LPITEMIDLIST pidl = NULL;

hr = SHGetMalloc(&lpMalloc);

if (FAILED(hr))
return 0;

pidl=(LPITEMIDLIST)lpMalloc->Alloc(cbSize);

if (pidl)
memset(pidl, 0, cbSize); // zero-init for external task alloc

if (lpMalloc)
lpMalloc->Release();

return pidl;
}

LPITEMIDLIST CShellTreeCtrl::GetNextItemID(LPCITEMIDLIST pidl)
{
// Check for valid pidl.
if(pidl == NULL)
return NULL;

// Get the size of the specified item identifier.
int cb = pidl->mkid.cb;

// If the size is zero, it is the end of the list.
if (cb == 0)
return NULL;

// Add cb to pidl (casting to increment by bytes).
pidl = (LPITEMIDLIST) (((LPBYTE) pidl) + cb);

// Return NULL if it is null-terminating, or a pidl otherwise.
if( pidl->mkid.cb == 0 )
return NULL;
else
return (LPITEMIDLIST)pidl;
//return (pidl->mkid.cb == 0) ? NULL : (LPITEMIDLIST) pidl;
}
回复
相关推荐
发帖
界面
创建于2007-09-28

1.5w+

社区成员

VC/MFC 界面
申请成为版主
帖子事件
创建了帖子
2005-08-22 06:06
社区公告
暂无公告