📄 pidl.cpp
字号:
/*****************************************************************
*
* Project.....: That crazy little thing called PIDL
* Application.: PIDL.exe
* Module......: PIDL.cpp
* Description.: Application main module
* Compiler....: MS Visual C++
* Written by..: D. Esposito
* Environment.: Windows 9x/NT
*
******************************************************************/
/*---------------------------------------------------------------*/
// PRAGMA section
/*---------------------------------------------------------------*/
// Force the linker to add the following libraries.
// In doing so we prevent the use of MFC classes.
#ifdef _MSC_VER
#pragma comment(lib, "kernel32.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "shell32.lib")
#pragma comment(lib, "comctl32.lib")
#endif
/*---------------------------------------------------------------*/
// INCLUDE section
/*---------------------------------------------------------------*/
#include "Pidl.h"
#include <commctrl.h>
#include <shellapi.h>
#include <shlobj.h>
#include "resource.h"
/*---------------------------------------------------------------*/
// GLOBAL section
/*---------------------------------------------------------------*/
// Data
HICON g_hIconLarge;
HICON g_hIconSmall;
HIMAGELIST g_himl;
// Typedefs
typedef BOOL (CALLBACK *FOLDERCONTENTPROC)(LPCSTR, HICON, DWORD);
// Functions
void OnInitDialog(HWND);
void OnOK(HWND);
void DoSearchPath(HWND);
HRESULT SHPathToPidlEx(LPCTSTR, LPITEMIDLIST*, LPSHELLFOLDER);
void ClearUI(HWND);
void StrretToString(LPITEMIDLIST, LPSTRRET, LPSTR);
int SHEnumFolderContent(LPSHELLFOLDER, FOLDERCONTENTPROC, DWORD, LPITEMIDLIST*);
void DoEnumeratePidl(HWND);
// Callbacks
BOOL CALLBACK APP_DlgProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK SearchText(LPCSTR, HICON, DWORD);
BOOL CALLBACK ShowFolderContent(LPCSTR, HICON, DWORD);
/*---------------------------------------------------------------*/
// Procedure....: WinMain()
// Description..: Entry point in any Windows program
// Input........: HINSTANCE, HINSTANCE, LPSTR, int
// Output.......: INT
/*---------------------------------------------------------------*/
int APIENTRY WinMain(
HINSTANCE hInstance, HINSTANCE hPrevious, LPTSTR lpsz, int iCmd)
{
// Save global data
g_hIconLarge = static_cast<HICON>(LoadImage(hInstance, "APP_ICON", IMAGE_ICON,
GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CXICON), 0));
g_hIconSmall = static_cast<HICON>(LoadImage(hInstance, "APP_ICON", IMAGE_ICON,
GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CXSMICON), 0));
g_himl = 0;
// Enable common controls
INITCOMMONCONTROLSEX iccex;
iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
iccex.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&iccex);
// Run main dialog
BOOL b = DialogBox(hInstance, "DLG_MAIN", NULL, APP_DlgProc);
// Exit
DestroyIcon(g_hIconLarge);
DestroyIcon(g_hIconSmall);
return b;
}
/*---------------------------------------------------------------*/
// Procedure....: APP_DlgProc()
// Description..: Responds to all messages sent to the dialog
// Input........: HWND, UINT, WPARAM, LPARAM
// Output.......: BOOL
/*---------------------------------------------------------------*/
BOOL CALLBACK APP_DlgProc(HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
switch(uiMsg)
{
case WM_INITDIALOG:
OnInitDialog(hDlg);
break;
case WM_COMMAND:
switch(wParam)
{
case IDC_SEARCHPATH:
DoSearchPath(hDlg);
return FALSE;
case IDC_PIDLCONTENT:
DoEnumeratePidl(hDlg);
return FALSE;
case IDCANCEL:
EndDialog(hDlg, FALSE);
return FALSE;
}
break;
}
return FALSE;
}
/*****************************************************************
*
* Internals:
* - OnOK()
* - OnInitDialog()
*
******************************************************************/
/*---------------------------------------------------------------*/
// Procedure...: OnOK()
// Description.: Do something
// INPUT.......: HWND
// OUTPUT......: void
/*---------------------------------------------------------------*/
void OnOK(HWND hDlg)
{
return;
}
/*---------------------------------------------------------------*/
// Procedure...: OnInitDialog()
// Description.: Initialize the dialog
// INPUT.......: HWND
// OUTPUT......: void
/*---------------------------------------------------------------*/
void OnInitDialog(HWND hDlg)
{
// Set the icons (T/F as to Large/Small icon)
SendMessage(hDlg, WM_SETICON, FALSE, reinterpret_cast<LPARAM>(g_hIconSmall));
SendMessage(hDlg, WM_SETICON, TRUE, reinterpret_cast<LPARAM>(g_hIconLarge));
// Fill the combo box
HWND hwndCbo = GetDlgItem(hDlg, IDC_SPECIAL);
int i = ComboBox_AddString(hwndCbo, "Control Panel");
ComboBox_SetItemData(hwndCbo, i, CSIDL_CONTROLS);
i = ComboBox_AddString(hwndCbo, "Favorites");
ComboBox_SetItemData(hwndCbo, i, CSIDL_FAVORITES);
i = ComboBox_AddString(hwndCbo, "Printers");
ComboBox_SetItemData(hwndCbo, i, CSIDL_PRINTERS);
i = ComboBox_AddString(hwndCbo, "Fonts");
ComboBox_SetItemData(hwndCbo, i, CSIDL_FONTS);
i = ComboBox_AddString(hwndCbo, "SendTo");
ComboBox_SetItemData(hwndCbo, i, CSIDL_SENDTO);
ComboBox_SetCurSel(hwndCbo, 0);
}
void DoSearchPath(HWND hDlg)
{
LPITEMIDLIST pidl = NULL;
LPSHELLFOLDER pFolder = NULL;
LPSHELLFOLDER pSubFolder = NULL;
// Get the memory allocator
LPMALLOC pMalloc = NULL;
SHGetMalloc(&pMalloc);
// Get the name to search
TCHAR szName[MAX_PATH] = {0};
GetDlgItemText(hDlg, IDC_FOLDER, szName, MAX_PATH);
// Get the IShellFolder interface for the desktop
SHGetDesktopFolder(&pFolder);
// Try to find a match under Desktop
int iNumOfItems = SHEnumFolderContent(pFolder, NULL, 0, NULL);
int rc = SHEnumFolderContent(
pFolder, SearchText, reinterpret_cast<DWORD>(szName), &pidl);
// If not found, try under My Computer
if(rc == iNumOfItems)
{
// Bind to My Computer
LPITEMIDLIST pidlMyComp;
SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &pidlMyComp);
pFolder->BindToObject(pidlMyComp, NULL, IID_IShellFolder,
reinterpret_cast<LPVOID*>(&pSubFolder));
// Free the pointer to the desktop folder
pFolder->Release();
pMalloc->Free(pidlMyComp);
pFolder = pSubFolder;
// Scan My Computer
iNumOfItems = SHEnumFolderContent(pFolder, NULL, 0, NULL);
rc = SHEnumFolderContent(
pFolder, SearchText, reinterpret_cast<DWORD>(szName), &pidl);
if(rc == iNumOfItems)
{
// Make the last attempt: is it a path name?
HRESULT hr = SHPathToPidlEx(szName, &pidl, pFolder);
if(FAILED(hr))
{
Msg("\"%s\" not found under Desktop or My Computer.", szName);
pMalloc->Free(pidl);
pFolder->Release();
// Call a helper function to refresh the UI
ClearUI(hDlg);
return;
}
}
}
// If here, then:
// pidl points to the folder we need to bind to enumerate the content
// pFolder points to the IShellFolder of the pidl's parent folder
// Bind to the subfolder we're searching for
// pFolder can point to Desktop's or My Computer's IShellFolder
pFolder->BindToObject(pidl, NULL, IID_IShellFolder,
reinterpret_cast<LPVOID*>(&pSubFolder));
// Refresh UI (empty list view, image list and the like)
ClearUI(hDlg);
// Enumerate the content of the folder in the listview
HWND hwndListView = GetDlgItem(hDlg, IDC_LISTVIEW);
SHEnumFolderContent(pSubFolder, ShowFolderContent,
reinterpret_cast<DWORD>(hwndListView), NULL);
// Clean up
pFolder->Release();
pSubFolder->Release();
pMalloc->Free(pidl);
pMalloc->Release();
return;
}
HRESULT SHPathToPidlEx(LPCTSTR szPath, LPITEMIDLIST* ppidl, LPSHELLFOLDER pFolder)
{
OLECHAR wszPath[MAX_PATH] = {0};
ULONG nCharsParsed = 0;
LPSHELLFOLDER pShellFolder = NULL;
BOOL bFreeOnExit = FALSE;
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, -1, wszPath, MAX_PATH);
// Use the desktop's IShellFolder by default
if(pFolder == NULL)
{
SHGetDesktopFolder(&pShellFolder);
bFreeOnExit = TRUE;
}
else
pShellFolder = pFolder;
HRESULT hr = pShellFolder->ParseDisplayName(NULL, NULL, wszPath, &nCharsParsed, ppidl, NULL);
if(bFreeOnExit)
pShellFolder->Release();
return hr;
}
void ClearUI(HWND hDlg)
{
HWND hwndListView = GetDlgItem(hDlg, IDC_LISTVIEW);
ListView_DeleteAllItems(hwndListView);
ImageList_RemoveAll(g_himl);
SetDlgItemText(hDlg, IDC_FOUND, __TEXT("0 item(s) found."));
}
void StrretToString(LPITEMIDLIST pidl, LPSTRRET pStr, LPSTR pszBuf)
{
lstrcpy(pszBuf, "");
switch(pStr->uType)
{
case STRRET_WSTR: // Unicode string
WideCharToMultiByte(CP_ACP, 0, pStr->pOleStr, -1, pszBuf, MAX_PATH, NULL, NULL);
break;
case STRRET_OFFSET: // Offset
lstrcpy(pszBuf, reinterpret_cast<LPSTR>(pidl) + pStr->uOffset);
break;
case STRRET_CSTR: // ANSI string
lstrcpy(pszBuf, pStr->cStr);
break;
}
}
int SHEnumFolderContent(LPSHELLFOLDER pFolder, FOLDERCONTENTPROC pfn, DWORD dwData, LPITEMIDLIST* ppidl)
{
int iNumOfItems = 0;
// Enumerates the content
LPENUMIDLIST pEnumIDList = NULL;
pFolder->EnumObjects(NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &pEnumIDList);
ULONG ulFetched = 0;
LPITEMIDLIST pItem = NULL;
while(NOERROR == pEnumIDList->Next(1, &pItem, &ulFetched))
{
STRRET sName;
TCHAR szBuf[MAX_PATH] = {0};
pFolder->GetDisplayNameOf(pItem, 0, &sName);
StrretToString(pItem, &sName, szBuf);
// Invoke callback
if(pfn)
{
// Get the icon
UINT u = 0;
int iIconIndex = 0;
HICON hIcon = NULL;
HICON hIconSm = NULL;
TCHAR szIconFile[MAX_PATH] = {0};
LPEXTRACTICON pExtractIcon = NULL;
pFolder->GetUIObjectOf(NULL, 1, const_cast<LPCITEMIDLIST*>(&pItem),
IID_IExtractIcon, NULL, reinterpret_cast<LPVOID*>(&pExtractIcon));
pExtractIcon->GetIconLocation(0, szIconFile, MAX_PATH, &iIconIndex, &u);
pExtractIcon->Extract(szIconFile, iIconIndex, &hIcon, &hIconSm, MAKELONG(32, 16));
pExtractIcon->Release();
if(hIcon == NULL)
ExtractIconEx(szIconFile, iIconIndex, &hIcon, NULL, 1);
if(!pfn(szBuf, hIcon, dwData))
{
// Returns the current PIDL
if(ppidl != NULL)
*ppidl = pItem;
break;
}
}
++iNumOfItems;
}
return iNumOfItems;
}
BOOL CALLBACK SearchText(LPCSTR pszItem, HICON hIcon, DWORD dwData)
{
return static_cast<BOOL>(lstrcmpi(pszItem, reinterpret_cast<LPCSTR>(dwData)));
}
BOOL CALLBACK ShowFolderContent(LPCSTR pszItem, HICON hIcon, DWORD dwData)
{
// Create the imagelist
int iIconWidth = GetSystemMetrics(SM_CXICON);
int iIconHeight = GetSystemMetrics(SM_CYICON);
if(g_himl == NULL)
g_himl = ImageList_Create(iIconWidth, iIconHeight, ILC_MASK, 1, 0);
int iIconPos = ImageList_AddIcon(g_himl, hIcon);
HWND hwndListView = reinterpret_cast<HWND>(dwData);
ListView_SetImageList(hwndListView, g_himl, LVSIL_NORMAL);
LV_ITEM lvi;
ZeroMemory(&lvi, sizeof(LV_ITEM));
lvi.mask = LVIF_TEXT | LVIF_IMAGE;
lvi.pszText = const_cast<LPSTR>(pszItem);
lvi.cchTextMax = lstrlen(pszItem);
lvi.iImage = iIconPos;
ListView_InsertItem(hwndListView, &lvi);
// Update count
TCHAR s[MAX_PATH] = {0};
wsprintf(s, "%d item(s) found.", ListView_GetItemCount(hwndListView));
SetDlgItemText(GetParent(hwndListView), IDC_FOUND, s);
return TRUE;
}
void DoEnumeratePidl(HWND hDlg)
{
LPITEMIDLIST pidl = NULL;
// Get the special folder and its PIDL
HWND hwndCbo = GetDlgItem(hDlg, IDC_SPECIAL);
int i = ComboBox_GetCurSel(hwndCbo);
int nFolder = ComboBox_GetItemData(hwndCbo, i);
SHGetSpecialFolderLocation(NULL, nFolder, &pidl);
// Get the IShellFolder interface
LPSHELLFOLDER pFolder = NULL;
SHGetDesktopFolder(&pFolder);
// Bind to subfolder
LPSHELLFOLDER pSubFolder = NULL;
pFolder->BindToObject(pidl, NULL, IID_IShellFolder,
reinterpret_cast<LPVOID*>(&pSubFolder));
pFolder->Release();
pFolder = pSubFolder;
// Clear the program's UI
ClearUI(hDlg);
// Enumerate the content
HWND hwndListView = GetDlgItem(hDlg, IDC_LISTVIEW);
SHEnumFolderContent(pFolder, ShowFolderContent,
reinterpret_cast<DWORD>(hwndListView), NULL);
// Clean up
LPMALLOC pMalloc = NULL;
SHGetMalloc(&pMalloc);
pMalloc->Free(pidl);
pMalloc->Release();
pFolder->Release();
}
/* End of file: Pidl.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -