📄 shfolder.cpp
字号:
// shfolder.cpp
#include <windows.h>
#include <shlobj.h>
#include <stdlib.h>
#include <string.h>
#include "msc.h"
#include "shfolder.h"
#ifdef _WIN64
#define ua __unaligned
#else
#define ua
#endif
static ITEMIDLIST *WINAPI ShOpenItemIdListInternal ( wchar_t *szPath ) ;
static HRESULT ShGetAttributesInternal ( const ITEMIDLIST *pItemIdList, SFGAOF *pSfGaof ) ;
static HRESULT ShBindToParent ( const ITEMIDLIST *pItemIdList, REFIID RefIid, void **ppObject, const ITEMIDLIST ua **pItemIdListLast ) ;
static ITEMIDLIST *ShILCombine ( const ITEMIDLIST *pBase, const ITEMIDLIST *pAdd ) ;
static const ITEMIDLIST ua *ShILFindLastID ( const ITEMIDLIST *pItemIdList ) ;
static size_t ShILGetSize ( const ITEMIDLIST *pItemIdList ) ;
static HRESULT StrretToBufA ( STRRET *pStrret, const ITEMIDLIST *pItemIdList, char *szBuffer, int nBufferSize ) ;
static HRESULT StrretToBufW ( STRRET *pStrret, const ITEMIDLIST *pItemIdList, wchar_t *szBuffer, int nBufferSize ) ;
// IMalloc
#define ShAlloc CoTaskMemAlloc
#define ShFree CoTaskMemFree
// This function is not supported in Win95
#ifndef NTFUNC_IMPORT_IMPLICITLY
#define SHGetPathFromIDListW SHGetPathFromIDListW_
#define ShellExecuteExW ShellExecuteExW_
typedef BOOL ( WINAPI *SHGETPATHFROMIDLISTW ) ( const ITEMIDLIST *pidl, LPWSTR pszPath ) ;
typedef BOOL ( WINAPI *SHELLEXECUTEEXW ) ( LPSHELLEXECUTEINFOW lpExecInfo ) ;
static HINSTANCE hShell32 ;
static SHGETPATHFROMIDLISTW SHGetPathFromIDListW ;
static SHELLEXECUTEEXW ShellExecuteExW ;
static int FreeLibraryOnDetach ( void ) ;
#endif
///////////////////////////////////
// ITEMIDLIST 偺庢摼偲夝曻 //
///////////////////////////////////
// 僷僗柤偐傜 ITEMIDLIST 傪庢摼偡傞乮ANSI斉乯
// szPath 偵偼僼儖僷僗柤丄傑偨偼 GUID 柤 "::{GUID}" 傪巜掕
// 惉岟偟偨傜 ITEMIDLIST 偺億僀儞僞傪丄幐攕偟偨傜 NULL 傪曉偡
ITEMIDLIST *WINAPI ShOpenItemIdListA ( const char *szPath ) {
wchar_t szPathTmp [ MAX_PATH ] ;
if ( ! MultiByteToWideChar ( CP_ACP, 0, szPath, -1, szPathTmp, MAX_PATH ) ) return NULL ;
return ShOpenItemIdListInternal ( szPathTmp ) ;
}
// 僷僗柤偐傜 ITEMIDLIST 傪庢摼偡傞乮UNICODE斉乯
// szPath 偵偼僼儖僷僗柤丄傑偨偼 GUID 柤 "::{GUID}" 傪巜掕
// 惉岟偟偨傜 ITEMIDLIST 偺億僀儞僞傪丄幐攕偟偨傜 NULL 傪曉偡
ITEMIDLIST *WINAPI ShOpenItemIdListW ( const wchar_t *szPath ) {
wchar_t *szPathTmp = wcsdup_max ( szPath, MAX_LONG_PATH ) ;
if ( ! szPathTmp ) return NULL ;
ITEMIDLIST *pItemIdList = ShOpenItemIdListInternal ( szPathTmp ) ;
free ( szPathTmp ) ;
return pItemIdList ;
}
// ShOpenItemIdList 偺壓惪偗娭悢
// 惉岟偟偨傜 ITEMIDLIST 偺億僀儞僞傪丄幐攕偟偨傜 NULL 傪曉偡
static ITEMIDLIST *WINAPI ShOpenItemIdListInternal ( wchar_t *szPath ) {
ITEMIDLIST *pItemIdList = NULL ;
IShellFolder *pIShellFolder ;
if ( SUCCEEDED ( SHGetDesktopFolder ( & pIShellFolder ) ) ) {
pIShellFolder->ParseDisplayName ( NULL, NULL, szPath, NULL, & pItemIdList, NULL ) ;
pIShellFolder->Release () ;
}
return pItemIdList ;
}
// 摿庩側僼僅儖僟乕偺 ITEMIDLIST 傪庢摼偡傞
// 惉岟偟偨傜 ITEMIDLIST 偺億僀儞僞傪丄幐攕偟偨傜 NULL 傪曉偡
ITEMIDLIST *WINAPI ShOpenSpecialItemIdList ( int nCsidl ) {
ITEMIDLIST *pItemIdList ;
if ( ! SUCCEEDED ( SHGetSpecialFolderLocation ( NULL, nCsidl, & pItemIdList ) ) ) pItemIdList = NULL ;
return pItemIdList ;
}
// ITEMIDLIST 傪暵偠傞
// 惉岟偟偨傜 0 傪, 幐攕偟偨傜 0 埲奜傪曉偡
int WINAPI ShCloseItemIdList ( ITEMIDLIST *pItemIdList ) {
ShFree ( pItemIdList ) ;
return 0 ;
}
///////////////////////////////////
// ITEMIDLIST 偺夝愅 //
///////////////////////////////////
// ITEMIDLIST 偐傜僷僗柤傪庢摼偡傞乮ANSI斉乯
// 惉岟偟偨傜 0 傪, 幐攕偟偨傜 0 埲奜傪曉偡
int WINAPI ShGetPathA ( const ITEMIDLIST *pItemIdList, char *szPath ) {
*szPath = 0 ;
int nRetValue = 1 ;
if ( SHGetPathFromIDListA ( pItemIdList, szPath ) ) nRetValue = 0 ;
return nRetValue ;
}
// ITEMIDLIST 偐傜僷僗柤傪庢摼偡傞乮UNICODE斉乯
// 惉岟偟偨傜 0 傪, 幐攕偟偨傜 0 埲奜傪曉偡
int WINAPI ShGetPathW ( const ITEMIDLIST *pItemIdList, wchar_t *szPath ) {
*szPath = 0 ;
int nRetValue = 1 ;
#ifndef NTFUNC_IMPORT_IMPLICITLY
if ( ! hShell32 && ( hShell32 = LoadLibraryW ( L"SHELL32.DLL" ) ) ) FreeLibraryOnDetach () ;
if ( GETPROCADDRESS ( hShell32, SHGETPATHFROMIDLISTW, SHGetPathFromIDListW ) ) return 1 ;
#endif
if ( SHGetPathFromIDListW ( pItemIdList, szPath ) ) nRetValue = 0 ;
return nRetValue ;
}
// ITEMIDLIST 偐傜昞帵柤傪庢摼偡傞乮ANSI斉乯
// 惉岟偟偨傜 0 傪, 幐攕偟偨傜 0 埲奜傪曉偡
int WINAPI ShGetDisplayNameA ( const ITEMIDLIST *pItemIdList, char *szName ) {
*szName = 0 ;
int nRetValue = 1 ;
IShellFolder *pIShellFolder ;
if ( SUCCEEDED ( ShBindToParent ( pItemIdList, IID_IShellFolder, (void**) & pIShellFolder, & pItemIdList ) ) ) {
STRRET Strret ;
if ( SUCCEEDED ( pIShellFolder->GetDisplayNameOf ( pItemIdList, SHGDN_INFOLDER, & Strret ) ) ) {
if ( SUCCEEDED ( StrretToBufA ( & Strret, pItemIdList, szName, MAX_PATH ) ) ) nRetValue = 0 ;
}
pIShellFolder->Release () ;
}
return nRetValue ;
}
// ITEMIDLIST 偐傜昞帵柤傪庢摼偡傞乮UNICODE斉乯
// 惉岟偟偨傜 0 傪, 幐攕偟偨傜 0 埲奜傪曉偡
int WINAPI ShGetDisplayNameW ( const ITEMIDLIST *pItemIdList, wchar_t *szName ) {
*szName = 0 ;
int nRetValue = 1 ;
IShellFolder *pIShellFolder ;
if ( SUCCEEDED ( ShBindToParent ( pItemIdList, IID_IShellFolder, (void**) & pIShellFolder, & pItemIdList ) ) ) {
STRRET Strret ;
if ( SUCCEEDED ( pIShellFolder->GetDisplayNameOf ( pItemIdList, SHGDN_INFOLDER, & Strret ) ) ) {
if ( SUCCEEDED ( StrretToBufW ( & Strret, pItemIdList, szName, MAX_PATH ) ) ) nRetValue = 0 ;
}
pIShellFolder->Release () ;
}
return nRetValue ;
}
// ITEMIDLIST 偐傜僷僗柤傑偨偼 GUID 柤傪庢摼偡傞乮ANSI斉乯
// 惉岟偟偨傜 0 傪, 幐攕偟偨傜 0 埲奜傪曉偡
int WINAPI ShGetNameForParsingA ( const ITEMIDLIST *pItemIdList, char *szName ) {
*szName = 0 ;
int nRetValue = 1 ;
IShellFolder *pIShellFolder ;
if ( SUCCEEDED ( ShBindToParent ( pItemIdList, IID_IShellFolder, (void**) & pIShellFolder, & pItemIdList ) ) ) {
STRRET Strret ;
if ( SUCCEEDED ( pIShellFolder->GetDisplayNameOf ( pItemIdList, SHGDN_FORPARSING, & Strret ) ) ) {
if ( SUCCEEDED ( StrretToBufA ( & Strret, pItemIdList, szName, MAX_PATH ) ) ) nRetValue = 0 ;
}
pIShellFolder->Release () ;
}
return nRetValue ;
}
// ITEMIDLIST 偐傜僷僗柤傑偨偼 GUID 柤傪庢摼偡傞乮UNICODE斉乯
// 惉岟偟偨傜 0 傪, 幐攕偟偨傜 0 埲奜傪曉偡
int WINAPI ShGetNameForParsingW ( const ITEMIDLIST *pItemIdList, wchar_t *szName ) {
*szName = 0 ;
int nRetValue = 1 ;
IShellFolder *pIShellFolder ;
if ( SUCCEEDED ( ShBindToParent ( pItemIdList, IID_IShellFolder, (void**) & pIShellFolder, & pItemIdList ) ) ) {
STRRET Strret ;
if ( SUCCEEDED ( pIShellFolder->GetDisplayNameOf ( pItemIdList, SHGDN_FORPARSING, & Strret ) ) ) {
if ( SUCCEEDED ( StrretToBufW ( & Strret, pItemIdList, szName, MAX_PATH ) ) ) nRetValue = 0 ;
}
pIShellFolder->Release () ;
}
return nRetValue ;
}
// ITEMIDLIST 偐傜懏惈傪庢摼偡傞
// 惉岟偟偨傜 懏惈乮SFGAOF乯傪, 幐攕偟偨傜 (unsigned long) -1 傪曉偡
SFGAOF WINAPI ShGetAttributes ( const ITEMIDLIST *pItemIdList ) {
SFGAOF SfGaof ;
if ( ! SUCCEEDED ( ShGetAttributesInternal ( pItemIdList, & SfGaof ) ) ) SfGaof = (SFGAOF) -1 ;
return SfGaof ;
}
// ITEMIDLIST 偐傜 CSIDL 傪庢摼偡傞
// 惉岟偟偨傜 CSIDL 傪丄幐攕偟偨傜晧悢傪曉偡
int WINAPI ShGetCsidl ( const ITEMIDLIST *pItemIdList ) {
int nRetValue = -1 ;
IShellFolder *pIShellFolder ;
if ( SUCCEEDED ( SHGetDesktopFolder ( & pIShellFolder ) ) ) {
for ( int nCsidl = CSIDL_DESKTOP ; nCsidl <= CSIDL_MAX ; nCsidl ++ ) {
ITEMIDLIST *pItemIdListTmp = ShOpenSpecialItemIdList ( nCsidl ) ;
if ( pItemIdListTmp ) {
HRESULT hResult = pIShellFolder->CompareIDs ( 0, pItemIdList, pItemIdListTmp ) ;
if ( SUCCEEDED ( hResult ) && ! (short) HRESULT_CODE ( hResult ) ) {
nRetValue = nCsidl ;
break ;
}
ShCloseItemIdList ( pItemIdListTmp ) ;
}
}
pIShellFolder->Release () ;
}
return nRetValue ;
}
// 擇偮偺 ITEMIDLIST 傪斾妑
// pIsError 偼 NULL 偱傕壜
// 惉岟偟偨傜 pIsError 偵 0 傪僙僢僩偟丄斾妑寢壥傪曉偡
// 幐攕偟偨傜 pIsError 偵 0 埲奜傪僙僢僩偡傞
int WINAPI ShCompareItemIdList ( const ITEMIDLIST *pItemIdList1, const ITEMIDLIST *pItemIdList2, int *pIsError ) {
HRESULT hResult = E_FAIL ;
IShellFolder *pIShellFolder ;
if ( SUCCEEDED ( SHGetDesktopFolder ( & pIShellFolder ) ) ) {
hResult = pIShellFolder->CompareIDs ( 0, pItemIdList1, pItemIdList2 ) ;
pIShellFolder->Release () ;
}
if ( pIsError ) *pIsError = ! SUCCEEDED ( hResult ) ;
return (short) HRESULT_CODE ( hResult ) ;
}
///////////////////////////////////
// ITEMIDLIST 偺楍嫇 //
///////////////////////////////////
// 僼僅儖僟偺 ITEMIDLIST 偐傜 巕 ITEMIDLIST 傪楍嫇
// 僐乕儖僶僢僋娭悢偑 0 傪曉偟偨傜丄楍嫇傪掆巭
// 0 埲奜傪曉偟偨傜丄楍嫇傪宲懕
// 惉岟偟偨傜 0 傪, 幐攕偟偨傜 0 埲奜傪曉偡
int WINAPI ShEnumItemIdList ( const ITEMIDLIST *pItemIdList, int ( CALLBACK *CallbackProc ) ( ITEMIDLIST *pItemIdList, LPARAM lParam ), unsigned long dwFlags, LPARAM lParam ) {
int nRetValue = 1 ;
IShellFolder *pIShellFolder ;
const ITEMIDLIST ua *pItemIdListLast ;
if ( SUCCEEDED ( ShBindToParent ( pItemIdList, IID_IShellFolder, (void**) & pIShellFolder, & pItemIdListLast ) ) ) {
IShellFolder *pIShellFolderSub ;
if ( IsDesktopItemIdList ( pItemIdListLast ) ) pIShellFolderSub = pIShellFolder ;
else if ( ! SUCCEEDED ( pIShellFolder->BindToObject ( pItemIdListLast, NULL, IID_IShellFolder, (void**) & pIShellFolderSub ) ) ) pIShellFolderSub = NULL ;
if ( pIShellFolderSub ) {
unsigned long dwEnumFlags = ( SHCONTF_FOLDERS | SHCONTF_NONFOLDERS ) ;
if ( dwFlags & ENUMITEMIDLIST_FOLDER_ONLY ) dwEnumFlags &= ~ SHCONTF_NONFOLDERS ;
if ( dwFlags & ENUMITEMIDLIST_FILE_ONLY ) dwEnumFlags &= ~ SHCONTF_FOLDERS ;
if ( dwFlags & ENUMITEMIDLIST_HIDDEN ) dwEnumFlags |= SHCONTF_INCLUDEHIDDEN ;
IEnumIDList *pIEnumIdList ;
if ( SUCCEEDED ( pIShellFolderSub->EnumObjects ( NULL, dwEnumFlags, & pIEnumIdList ) ) ) {
nRetValue = 0 ;
ITEMIDLIST *pItemIdListSub ;
unsigned long dwNumber ;
while ( ! pIEnumIdList->Next ( 1, & pItemIdListSub, & dwNumber ) ) {
ITEMIDLIST *pItemIdListSubFul = ShILCombine ( pItemIdList, pItemIdListSub ) ;
ShCloseItemIdList ( pItemIdListSub ) ;
if ( ! pItemIdListSubFul ) continue ;
int nResut = CallbackProc ( pItemIdListSubFul, lParam ) ;
if ( ! ( dwFlags & ENUMITEMIDLIST_CLOSE_BY_USER ) ) ShCloseItemIdList ( pItemIdListSubFul ) ;
if ( ! nResut ) break ;
}
pIEnumIdList->Release () ;
}
if ( pIShellFolderSub != pIShellFolder ) pIShellFolderSub->Release () ;
}
pIShellFolder->Release () ;
}
return nRetValue ;
}
///////////////////////////////////
// ITEMIDLIST 偺憖嶌 //
///////////////////////////////////
// 摿暿側僼僅儖僟柤傪奐偔乮ANSI斉乯
// 惉岟偟偨傜 0 傪, 幐攕偟偨傜 0 埲奜傪曉偡
int WINAPI ShExecuteA ( HWND hWnd, const char *szVerb, const ITEMIDLIST *pItemIdList, const char *szArguments, const char *szDirectory, int nShowCmd ) {
size_t nLength = ShILGetSize ( pItemIdList ) ;
ITEMIDLIST *pItemIdListTmp = (ITEMIDLIST*) malloc ( nLength ) ;
if ( ! pItemIdListTmp ) return 1 ;
memmove ( pItemIdListTmp, pItemIdList, nLength ) ;
SHELLEXECUTEINFOA ShellExecuteInfo = { 0 } ;
ShellExecuteInfo.cbSize = sizeof(SHELLEXECUTEINFOA) ;
ShellExecuteInfo.hwnd = hWnd ;
ShellExecuteInfo.lpVerb = szVerb ;
ShellExecuteInfo.lpParameters = szArguments ;
ShellExecuteInfo.lpDirectory = szDirectory ;
ShellExecuteInfo.nShow = nShowCmd ;
ShellExecuteInfo.fMask = SEE_MASK_INVOKEIDLIST | SEE_MASK_FLAG_NO_UI ;
ShellExecuteInfo.lpIDList = pItemIdListTmp ;
int nResult = ! ShellExecuteExA ( & ShellExecuteInfo ) ;
free ( pItemIdListTmp ) ;
return nResult ;
}
// 摿暿側僼僅儖僟柤傪奐偔乮UNICODE斉乯
// 惉岟偟偨傜 0 傪, 幐攕偟偨傜 0 埲奜傪曉偡
int WINAPI ShExecuteW ( HWND hWnd, const wchar_t *szVerb, const ITEMIDLIST *pItemIdList, const wchar_t *szArguments, const wchar_t *szDirectory, int nShowCmd ) {
#ifndef NTFUNC_IMPORT_IMPLICITLY
if ( ! hShell32 && ( hShell32 = LoadLibraryW ( L"SHELL32.DLL" ) ) ) FreeLibraryOnDetach () ;
if ( GETPROCADDRESS ( hShell32, SHELLEXECUTEEXW, ShellExecuteExW ) ) return 1 ;
#endif
size_t nLength = ShILGetSize ( pItemIdList ) ;
ITEMIDLIST *pItemIdListTmp = (ITEMIDLIST*) malloc ( nLength ) ;
if ( ! pItemIdListTmp ) return 1 ;
memmove ( pItemIdListTmp, pItemIdList, nLength ) ;
SHELLEXECUTEINFOW ShellExecuteInfo = { 0 } ;
ShellExecuteInfo.cbSize = sizeof(SHELLEXECUTEINFOW) ;
ShellExecuteInfo.hwnd = hWnd ;
ShellExecuteInfo.lpVerb = szVerb ;
ShellExecuteInfo.lpParameters = szArguments ;
ShellExecuteInfo.lpDirectory = szDirectory ;
ShellExecuteInfo.nShow = nShowCmd ;
ShellExecuteInfo.fMask = SEE_MASK_INVOKEIDLIST | SEE_MASK_FLAG_NO_UI ;
ShellExecuteInfo.lpIDList = pItemIdListTmp ;
int nResult = ! ShellExecuteExW ( & ShellExecuteInfo ) ;
free ( pItemIdListTmp ) ;
return nResult ;
}
///////////////////////////////////
// ITEMIDLIST 峏怴偺捠抦 //
///////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -