From 5136f57f12e99f2be686e3a6d9b4eaad2e436428 Mon Sep 17 00:00:00 2001 From: Michael Jung Date: Tue, 3 Jan 2006 13:23:44 +0100 Subject: [PATCH] shell32: Helper function for unicode support in folder and file pidls. --- dlls/shell32/pidl.c | 53 +++++++++++++++++++++++++++++++++++++++++---- dlls/shell32/pidl.h | 15 +++++++++++++ 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/dlls/shell32/pidl.c b/dlls/shell32/pidl.c index b39fb249742..fb859495cb0 100644 --- a/dlls/shell32/pidl.c +++ b/dlls/shell32/pidl.c @@ -1811,15 +1811,21 @@ DWORD _ILSimpleGetText (LPCITEMIDLIST pidl, LPSTR szOut, UINT uOutSize) */ DWORD _ILSimpleGetTextW (LPCITEMIDLIST pidl, LPWSTR szOut, UINT uOutSize) { - DWORD dwReturn; + DWORD dwReturn; char szTemp[MAX_PATH]; + FileStructW *pFileStructW = _ILGetFileStructW(pidl); TRACE("(%p %p %x)\n",pidl,szOut,uOutSize); - dwReturn = _ILSimpleGetText(pidl, szTemp, 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, MAX_PATH)) - *szOut = 0; + if (!MultiByteToWideChar(CP_ACP, 0, szTemp, -1, szOut, uOutSize)) + *szOut = 0; + } TRACE("-- (%p=%s 0x%08lx)\n",szOut,debugstr_w(szOut),dwReturn); return dwReturn; @@ -1938,6 +1944,45 @@ IID* _ILGetGUIDPointer(LPCITEMIDLIST pidl) 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 * diff --git a/dlls/shell32/pidl.h b/dlls/shell32/pidl.h index df3d1f25f70..691aa2aa51f 100644 --- a/dlls/shell32/pidl.h +++ b/dlls/shell32/pidl.h @@ -143,6 +143,20 @@ typedef struct tagFileStruct The second the dos name when needed or just 0x00 */ } FileStruct; +/* At least on WinXP, this struct is appended with 2-byte-alignment to FileStruct. There follows + * a WORD member after the wszName string, which gives the offset from the beginning of the PIDL + * to the FileStructW member. */ +typedef struct tagFileStructW { + WORD cbLen; + BYTE dummy1[6]; + WORD uCreationDate; + WORD uCreationTime; + WORD uLastAccessDate; + WORD uLastAccessTime; + BYTE dummy2[4]; + WCHAR wszName[1]; +} FileStructW; + typedef struct tagValueW { WCHAR name[1]; @@ -240,6 +254,7 @@ LPPIDLDATA _ILGetDataPointer (LPCITEMIDLIST); LPSTR _ILGetTextPointer (LPCITEMIDLIST); LPSTR _ILGetSTextPointer (LPCITEMIDLIST); IID *_ILGetGUIDPointer (LPCITEMIDLIST pidl); +FileStructW *_ILGetFileStructW (LPCITEMIDLIST pidl); /* * debug helper