📄 pidl.c
字号:
}
BOOL _ILIsValue(LPCITEMIDLIST pidl)
{
LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
TRACE("(%p)\n",pidl);
return (pidl && lpPData && PT_VALUE == lpPData->type);
}
BOOL _ILIsCPanelStruct(LPCITEMIDLIST pidl)
{
LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
TRACE("(%p)\n",pidl);
return (pidl && lpPData && (lpPData->type == 0));
}
/**************************************************************************
* _ILIsPidlSimple
*/
BOOL _ILIsPidlSimple(LPCITEMIDLIST pidl)
{
BOOL ret = TRUE;
if(! _ILIsDesktop(pidl)) /* pidl=NULL or mkid.cb=0 */
{
WORD len = pidl->mkid.cb;
LPCITEMIDLIST pidlnext = (LPCITEMIDLIST) (((const BYTE*)pidl) + len );
if (pidlnext->mkid.cb)
ret = FALSE;
}
TRACE("%s\n", ret ? "Yes" : "No");
return ret;
}
/**************************************************************************
*
* ### 3. section getting values from pidls ###
*/
/**************************************************************************
* _ILSimpleGetText
*
* gets the text for the first item in the pidl (eg. simple pidl)
*
* returns the length of the string
*/
DWORD _ILSimpleGetText (LPCITEMIDLIST pidl, LPSTR szOut, UINT uOutSize)
{
DWORD dwReturn=0;
LPSTR szSrc;
GUID const * riid;
char szTemp[MAX_PATH];
TRACE("(%p %p %x)\n",pidl,szOut,uOutSize);
if (!pidl)
return 0;
if (szOut)
*szOut = 0;
if (_ILIsDesktop(pidl))
{
/* desktop */
if (HCR_GetClassNameA(&CLSID_ShellDesktop, szTemp, MAX_PATH))
{
if (szOut)
lstrcpynA(szOut, szTemp, uOutSize);
dwReturn = strlen (szTemp);
}
}
else if (( szSrc = _ILGetTextPointer(pidl) ))
{
/* filesystem */
if (szOut)
lstrcpynA(szOut, szSrc, uOutSize);
dwReturn = strlen(szSrc);
}
else if (( riid = _ILGetGUIDPointer(pidl) ))
{
/* special folder */
if ( HCR_GetClassNameA(riid, szTemp, MAX_PATH) )
{
if (szOut)
lstrcpynA(szOut, szTemp, uOutSize);
dwReturn = strlen (szTemp);
}
}
else
{
ERR("-- no text\n");
}
TRACE("-- (%p=%s 0x%08lx)\n",szOut,debugstr_a(szOut),dwReturn);
return dwReturn;
}
/**************************************************************************
* _ILSimpleGetTextW
*
* gets the text for the first item in the pidl (eg. simple pidl)
*
* returns the length of the string
*/
DWORD _ILSimpleGetTextW (LPCITEMIDLIST pidl, LPWSTR szOut, UINT uOutSize)
{
DWORD dwReturn;
char szTemp[MAX_PATH];
FileStructW *pFileStructW = _ILGetFileStructW(pidl);
TRACE("(%p %p %x)\n",pidl,szOut,uOutSize);
if (pFileStructW) {
lstrcpynW(szOut, pFileStructW->wszName, uOutSize);
dwReturn = lstrlenW(pFileStructW->wszName);
} else {
dwReturn = _ILSimpleGetText(pidl, szTemp, MAX_PATH);
if (!MultiByteToWideChar(CP_ACP, 0, szTemp, -1, szOut, uOutSize))
*szOut = 0;
}
TRACE("-- (%p=%s 0x%08lx)\n",szOut,debugstr_w(szOut),dwReturn);
return dwReturn;
}
/**************************************************************************
*
* ### 4. getting pointers to parts of pidls ###
*
**************************************************************************
* _ILGetDataPointer()
*/
LPPIDLDATA _ILGetDataPointer(LPCITEMIDLIST pidl)
{
if(pidl && pidl->mkid.cb != 0x00)
return (LPPIDLDATA) &(pidl->mkid.abID);
return NULL;
}
/**************************************************************************
* _ILGetTextPointer()
* gets a pointer to the long filename string stored in the pidl
*/
LPSTR _ILGetTextPointer(LPCITEMIDLIST pidl)
{
/* TRACE(pidl,"(pidl%p)\n", pidl);*/
LPPIDLDATA pdata = _ILGetDataPointer(pidl);
if (!pdata)
return NULL;
switch (pdata->type)
{
case PT_GUID:
case PT_SHELLEXT:
case PT_YAGUID:
return NULL;
case PT_DRIVE:
case PT_DRIVE1:
case PT_DRIVE2:
case PT_DRIVE3:
return (LPSTR)&(pdata->u.drive.szDriveName);
case PT_FOLDER:
case PT_FOLDER1:
case PT_VALUE:
case PT_IESPECIAL1:
case PT_IESPECIAL2:
return (LPSTR)&(pdata->u.file.szNames);
case PT_WORKGRP:
case PT_COMP:
case PT_NETWORK:
case PT_NETPROVIDER:
case PT_SHARE:
return (LPSTR)&(pdata->u.network.szNames);
}
return NULL;
}
/**************************************************************************
* _ILGetSTextPointer()
* gets a pointer to the short filename string stored in the pidl
*/
LPSTR _ILGetSTextPointer(LPCITEMIDLIST pidl)
{
/* TRACE(pidl,"(pidl%p)\n", pidl); */
LPPIDLDATA pdata =_ILGetDataPointer(pidl);
if (!pdata)
return NULL;
switch (pdata->type)
{
case PT_FOLDER:
case PT_VALUE:
case PT_IESPECIAL1:
case PT_IESPECIAL2:
return (LPSTR)(pdata->u.file.szNames + strlen (pdata->u.file.szNames) + 1);
case PT_WORKGRP:
return (LPSTR)(pdata->u.network.szNames + strlen (pdata->u.network.szNames) + 1);
}
return NULL;
}
/**************************************************************************
* _ILGetGUIDPointer()
*
* returns reference to guid stored in some pidls
*/
IID* _ILGetGUIDPointer(LPCITEMIDLIST pidl)
{
LPPIDLDATA pdata =_ILGetDataPointer(pidl);
TRACE("%p\n", pidl);
if (!pdata)
return NULL;
TRACE("pdata->type 0x%04x\n", pdata->type);
switch (pdata->type)
{
case PT_SHELLEXT:
case PT_GUID:
case PT_YAGUID:
return &(pdata->u.guid.guid);
default:
TRACE("Unknown pidl type 0x%04x\n", pdata->type);
break;
}
return NULL;
}
/******************************************************************************
* _ILGetFileStructW [Internal]
*
* Get pointer the a SHITEMID's FileStructW field if present
*
* PARAMS
* pidl [I] The SHITEMID
*
* RETURNS
* Success: Pointer to pidl's FileStructW field.
* Failure: NULL
*/
FileStructW* _ILGetFileStructW(LPCITEMIDLIST pidl) {
FileStructW *pFileStructW;
WORD cbOffset;
if (!(_ILIsValue(pidl) || _ILIsFolder(pidl)))
return NULL;
cbOffset = *(WORD*)((LPBYTE)pidl + pidl->mkid.cb - sizeof(WORD));
pFileStructW = (FileStructW*)((LPBYTE)pidl + cbOffset);
/* Currently I don't see a fool prove way to figure out if a pidl is for sure of WinXP
* style with a FileStructW member. If we switch all our shellfolder-implementations to
* the new format, this won't be a problem. For now, we do as many sanity checks as possible. */
if (cbOffset & 0x1 || /* FileStructW member is word aligned in the pidl */
/* FileStructW is positioned after FileStruct */
cbOffset < sizeof(pidl->mkid.cb) + sizeof(PIDLTYPE) + sizeof(FileStruct) ||
/* There has to be enough space at cbOffset in the pidl to hold FileStructW and cbOffset */
cbOffset > pidl->mkid.cb - sizeof(cbOffset) - sizeof(FileStructW) ||
pidl->mkid.cb != cbOffset + pFileStructW->cbLen)
{
WARN("Invalid pidl format (cbOffset = %d)!\n", cbOffset);
return NULL;
}
return pFileStructW;
}
/*************************************************************************
* _ILGetFileDateTime
*
* Given the ItemIdList, get the FileTime
*
* PARAMS
* pidl [I] The ItemIDList
* pFt [I] the resulted FILETIME of the file
*
* RETURNS
* True if Successful
*
* NOTES
*
*/
BOOL _ILGetFileDateTime(LPCITEMIDLIST pidl, FILETIME *pFt)
{
LPPIDLDATA pdata = _ILGetDataPointer(pidl);
if (!pdata)
return FALSE;
switch (pdata->type)
{
case PT_FOLDER:
case PT_VALUE:
DosDateTimeToFileTime(pdata->u.file.uFileDate, pdata->u.file.uFileTime, pFt);
break;
default:
return FALSE;
}
return TRUE;
}
BOOL _ILGetFileDate (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
{
FILETIME ft,lft;
SYSTEMTIME time;
BOOL ret;
if (_ILGetFileDateTime( pidl, &ft ))
{
FileTimeToLocalFileTime(&ft, &lft);
FileTimeToSystemTime (&lft, &time);
ret = GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&time, NULL, pOut, uOutSize);
if (ret)
{
/* Append space + time without seconds */
pOut[ret-1] = ' ';
GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &time, NULL, &pOut[ret], uOutSize - ret);
}
}
else
{
pOut[0] = '\0';
ret = FALSE;
}
return ret;
}
/*************************************************************************
* _ILGetFileSize
*
* Given the ItemIdList, get the FileSize
*
* PARAMS
* pidl [I] The ItemIDList
* pOut [I] The buffer to save the result
* uOutsize [I] The size of the buffer
*
* RETURNS
* The FileSize
*
* NOTES
* pOut can be null when no string is needed
*
*/
DWORD _ILGetFileSize (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
{
LPPIDLDATA pdata = _ILGetDataPointer(pidl);
DWORD dwSize;
if (!pdata)
return 0;
switch (pdata->type)
{
case PT_VALUE:
dwSize = pdata->u.file.dwFileSize;
if (pOut)
StrFormatByteSizeA(dwSize, pOut, uOutSize);
return dwSize;
}
if (pOut)
*pOut = 0x00;
return 0;
}
BOOL _ILGetExtension (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
{
char szTemp[MAX_PATH];
const char * pPoint;
LPCITEMIDLIST pidlTemp=pidl;
TRACE("pidl=%p\n",pidl);
if (!pidl)
return FALSE;
pidlTemp = ILFindLastID(pidl);
if (!_ILIsValue(pidlTemp))
return FALSE;
if (!_ILSimpleGetText(pidlTemp, szTemp, MAX_PATH))
return FALSE;
pPoint = PathFindExtensionA(szTemp);
if (!*pPoint)
return FALSE;
pPoint++;
lstrcpynA(pOut, pPoint, uOutSize);
TRACE("%s\n",pOut);
return TRUE;
}
/*************************************************************************
* _ILGetFileType
*
* Given the ItemIdList, get the file type description
*
* PARAMS
* pidl [I] The ItemIDList (simple)
* pOut [I] The buffer to save the result
* uOutsize [I] The size of the buffer
*
* RETURNS
* nothing
*
* NOTES
* This function copies as much as possible into the buffer.
*/
void _ILGetFileType(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
{
if(_ILIsValue(pidl))
{
char sTemp[64];
if(uOutSize > 0)
pOut[0] = 0;
if (_ILGetExtension (pidl, sTemp, 64))
{
if (!( HCR_MapTypeToValueA(sTemp, sTemp, 64, TRUE)
&& HCR_MapTypeToValueA(sTemp, pOut, uOutSize, FALSE )))
{
lstrcpynA (pOut, sTemp, uOutSize - 6);
strcat (pOut, "-file");
}
}
}
else
lstrcpynA(pOut, "Folder", uOutSize);
}
/*************************************************************************
* _ILGetFileAttributes
*
* Given the ItemIdList, get the Attrib string format
*
* PARAMS
* pidl [I] The ItemIDList
* pOut [I] The buffer to save the result
* uOutsize [I] The size of the Buffer
*
* RETURNS
* Attributes
*
* FIXME
* return value 0 in case of error is a valid return value
*
*/
DWORD _ILGetFileAttributes(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
{
LPPIDLDATA pData = _ILGetDataPointer(pidl);
WORD wAttrib = 0;
int i;
if (!pData)
return 0;
switch(pData->type)
{
case PT_FOLDER:
case PT_VALUE:
wAttrib = pData->u.file.uFileAttribs;
break;
}
if(uOutSize >= 6)
{
i=0;
if(wAttrib & FILE_ATTRIBUTE_READONLY)
pOut[i++] = 'R';
if(wAttrib & FILE_ATTRIBUTE_HIDDEN)
pOut[i++] = 'H';
if(wAttrib & FILE_ATTRIBUTE_SYSTEM)
pOut[i++] = 'S';
if(wAttrib & FILE_ATTRIBUTE_ARCHIVE)
pOut[i++] = 'A';
if(wAttrib & FILE_ATTRIBUTE_COMPRESSED)
pOut[i++] = 'C';
pOut[i] = 0x00;
}
return wAttrib;
}
/*************************************************************************
* ILFreeaPidl
*
* free a aPidl struct
*/
void _ILFreeaPidl(LPITEMIDLIST * apidl, UINT cidl)
{
UINT i;
if (apidl)
{
for (i = 0; i < cidl; i++)
SHFree(apidl[i]);
SHFree(apidl);
}
}
/*************************************************************************
* ILCopyaPidl
*
* copies an aPidl struct
*/
LPITEMIDLIST* _ILCopyaPidl(LPCITEMIDLIST * apidlsrc, UINT cidl)
{
UINT i;
LPITEMIDLIST *apidldest;
apidldest = SHAlloc(cidl * sizeof(LPITEMIDLIST));
if (!apidlsrc)
return NULL;
for (i = 0; i < cidl; i++)
apidldest[i] = ILClone(apidlsrc[i]);
return apidldest;
}
/*************************************************************************
* _ILCopyCidaToaPidl
*
* creates aPidl from CIDA
*/
LPITEMIDLIST* _ILCopyCidaToaPidl(LPITEMIDLIST* pidl, LPIDA cida)
{
UINT i;
LPITEMIDLIST *dst;
dst = SHAlloc(cida->cidl * sizeof(LPITEMIDLIST));
if (!dst)
return NULL;
if (pidl)
*pidl = ILClone((LPITEMIDLIST)(&((LPBYTE)cida)[cida->aoffset[0]]));
for (i = 0; i < cida->cidl; i++)
dst[i] = ILClone((LPITEMIDLIST)(&((LPBYTE)cida)[cida->aoffset[i + 1]]));
return dst;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -