如何安全地从 SHNotify 事件中获取新文件名 (SHCNE_RENAMEITEM)
How to safely get the new filename from SHNotify event (SHCNE_RENAMEITEM)
我已经连接到 Windows shell,并且正在很好地接收到我隐藏的 CWnd
。
的通知事件
当我收到 SHCNE_RENAMEITEM
事件时,SHGetPathFromIDList()
函数 returns 我得到旧文件名,而不是重命名的新文件名。
我已经成功破解了一个指针并发现了新名称,但这对我来说并不是很安全。我尝试使用 ILNext
/ILGetNext
/ILIsEmpty
来迭代列表,但这些并没有给我新名称。有没有更安全的方法?
afx_msg LRESULT OnChange(WPARAM wParam, LPARAM lParam)
{
long lEvent = 0L;
PIDLIST_ABSOLUTE* rgpidl=nullptr;
TCHAR szFileOld[MAX_PATH] = L"[=11=]";
TCHAR szFileNew[MAX_PATH] = L"[=11=]";
HANDLE hNotifyLock = SHChangeNotification_Lock((HANDLE)wParam, (DWORD)lParam, &rgpidl, &lEvent);
if (!SHGetPathFromIDListW((struct _ITEMIDLIST*)*rgpidl, szFileOld))
return TRUE;
if (lEvent & SHCNE_RENAMEITEM)
{
struct _ITEMIDLIST* pNext = (struct _ITEMIDLIST*)*(&rgpidl[1]); // yes, I got lucky guessing the synatx.
if (ILIsEmpty(pNext)) // probably not much safety on this, but trying to be kind.
return TRUE;
if (!SHGetPathFromIDListW(pNext, szFileNew))
return TRUE;
}
// other code.
return FALSE;
}
我应该提到我的注册码正在使用新的交付方式。
BOOL fRecursive = FALSE;
UINT uMsg = WM_FILE_CHANGED;
long lEvents = SHCNE_UPDATEITEM | SHCNE_DELETE | SHCNE_CREATE | SHCNE_RENAMEITEM | SHCNE_UPDATEDIR;
int const nSources = SHCNRF_ShellLevel | SHCNRF_InterruptLevel | SHCNRF_NewDelivery;
SHChangeNotifyEntry const entries[] = { pidlWatch, fRecursive };
m_lNotificationRegistry = SHChangeNotifyRegister(m_pWnd->m_hWnd, nSources, lEvents, uMsg, ARRAYSIZE(entries), entries);
您的方向是正确的,但您的语法只是 over-complicated。 SHChangeNotification_Lock()
会给你一个指向 PIDL 数组的指针,你不需要花哨的 type-casts 来访问该数组的元素。
此外,您需要在退出回调函数之前调用 SHChangeNotification_Unlock()
。
尝试更像这样的东西:
afx_msg LRESULT OnChange(WPARAM wParam, LPARAM lParam)
{
long lEvent = 0L;
PIDLIST_ABSOLUTE* rgpidl = nullptr;
HANDLE hNotifyLock = SHChangeNotification_Lock((HANDLE)wParam, (DWORD)lParam, &rgpidl, &lEvent);
if (lEvent & SHCNE_RENAMEITEM)
{
WCHAR szFileOld[MAX_PATH] = L"[=10=]";
WCHAR szFileNew[MAX_PATH] = L"[=10=]";
SHGetPathFromIDListW(rgpidl[0], szFileOld);
SHGetPathFromIDListW(rgpidl[1], szFileNew);
}
// other code.
SHChangeNotification_Unlock(hNotifyLock);
return FALSE;
}
我已经连接到 Windows shell,并且正在很好地接收到我隐藏的 CWnd
。
当我收到 SHCNE_RENAMEITEM
事件时,SHGetPathFromIDList()
函数 returns 我得到旧文件名,而不是重命名的新文件名。
我已经成功破解了一个指针并发现了新名称,但这对我来说并不是很安全。我尝试使用 ILNext
/ILGetNext
/ILIsEmpty
来迭代列表,但这些并没有给我新名称。有没有更安全的方法?
afx_msg LRESULT OnChange(WPARAM wParam, LPARAM lParam)
{
long lEvent = 0L;
PIDLIST_ABSOLUTE* rgpidl=nullptr;
TCHAR szFileOld[MAX_PATH] = L"[=11=]";
TCHAR szFileNew[MAX_PATH] = L"[=11=]";
HANDLE hNotifyLock = SHChangeNotification_Lock((HANDLE)wParam, (DWORD)lParam, &rgpidl, &lEvent);
if (!SHGetPathFromIDListW((struct _ITEMIDLIST*)*rgpidl, szFileOld))
return TRUE;
if (lEvent & SHCNE_RENAMEITEM)
{
struct _ITEMIDLIST* pNext = (struct _ITEMIDLIST*)*(&rgpidl[1]); // yes, I got lucky guessing the synatx.
if (ILIsEmpty(pNext)) // probably not much safety on this, but trying to be kind.
return TRUE;
if (!SHGetPathFromIDListW(pNext, szFileNew))
return TRUE;
}
// other code.
return FALSE;
}
我应该提到我的注册码正在使用新的交付方式。
BOOL fRecursive = FALSE;
UINT uMsg = WM_FILE_CHANGED;
long lEvents = SHCNE_UPDATEITEM | SHCNE_DELETE | SHCNE_CREATE | SHCNE_RENAMEITEM | SHCNE_UPDATEDIR;
int const nSources = SHCNRF_ShellLevel | SHCNRF_InterruptLevel | SHCNRF_NewDelivery;
SHChangeNotifyEntry const entries[] = { pidlWatch, fRecursive };
m_lNotificationRegistry = SHChangeNotifyRegister(m_pWnd->m_hWnd, nSources, lEvents, uMsg, ARRAYSIZE(entries), entries);
您的方向是正确的,但您的语法只是 over-complicated。 SHChangeNotification_Lock()
会给你一个指向 PIDL 数组的指针,你不需要花哨的 type-casts 来访问该数组的元素。
此外,您需要在退出回调函数之前调用 SHChangeNotification_Unlock()
。
尝试更像这样的东西:
afx_msg LRESULT OnChange(WPARAM wParam, LPARAM lParam)
{
long lEvent = 0L;
PIDLIST_ABSOLUTE* rgpidl = nullptr;
HANDLE hNotifyLock = SHChangeNotification_Lock((HANDLE)wParam, (DWORD)lParam, &rgpidl, &lEvent);
if (lEvent & SHCNE_RENAMEITEM)
{
WCHAR szFileOld[MAX_PATH] = L"[=10=]";
WCHAR szFileNew[MAX_PATH] = L"[=10=]";
SHGetPathFromIDListW(rgpidl[0], szFileOld);
SHGetPathFromIDListW(rgpidl[1], szFileNew);
}
// other code.
SHChangeNotification_Unlock(hNotifyLock);
return FALSE;
}