Changelog - dlls/shell32/pidl.c Fix SHSimpleIDListFromPath to create a fully qualified Pidl and let it use an IFileSystemBindData object to help ShellFolder_ParseDisplayName to optimize creation of a "simple" fully qualified Pidl. (It currently still doesn't do that, but that is another patch) - dlls/shell32/shell32_main.h Add inline functions to convert ANSI strings to Unicode strings using the heap for A->W function calls. I do believe we shouldn't link shell32 to ntdll so the Rtl.. functions seem no option here. If this is wrong I would rather like to call those. License: X11/LGPL Rolf Kalbermatter Index: dlls/shell32/pidl.c =================================================================== RCS file: /home/wine/wine/dlls/shell32/pidl.c,v retrieving revision 1.88 diff -u -r1.88 pidl.c --- dlls/shell32/pidl.c 5 Sep 2003 23:08:31 -0000 1.88 +++ dlls/shell32/pidl.c 11 Sep 2003 18:03:18 -0000 @@ -42,6 +42,7 @@ #include "shlwapi.h" #include "pidl.h" +#include "shlfsbind.h" #include "debughlp.h" #include "wine/debug.h" @@ -807,46 +808,120 @@ return ILCreateFromPathA (path); } /************************************************************************* - * SHSimpleIDListFromPath [SHELL32.162] + * _ILParsePathW [internal] + * + * Creates an ItemIDList from a path and returns it. + * + * PARAMS + * path [I] path to parse and convert into an ItemIDList + * lpFindFile [I] pointer to buffer to initialize the FileSystem + * Bind Data object with + * bBindCtx [I] indicates to create a BindContext and assign a + * FileSystem Bind Data object + * ppidl [O] the newly create ItemIDList + * prgfInOut [I/O] requested attributes on input and actual + * attributes on return + * + * RETURNS + * NO_ERROR on success or an OLE error code + * + * NOTES + * If either lpFindFile is non-NULL or bBindCtx is TRUE, this function + * creates a BindContext object and assigns a FileSystem Bind Data object + * to it, passing the BindContext to IShellFolder_ParseDisplayName. Each + * IShellFolder uses that FileSystem Bind Data object of the BindContext + * to pass data about the current path element to the next object. This + * is used to avoid having to verify the current path element on disk, so + * that creating an ItemIDList from a non existing path still can work. */ -LPITEMIDLIST WINAPI SHSimpleIDListFromPathA (LPCSTR lpszPath) +static HRESULT WINAPI _ILParsePathW(LPCWSTR path, LPWIN32_FIND_DATAW lpFindFile, + BOOL bBindCtx, LPITEMIDLIST *ppidl, LPDWORD prgfInOut) { - LPITEMIDLIST pidl=NULL; - HANDLE hFile; - WIN32_FIND_DATAA stffile; + LPSHELLFOLDER pSF = NULL; + LPBC pBC = NULL; + HRESULT ret; - TRACE("path=%s\n", lpszPath); + TRACE("%s %p %d (%p)->%p (%p)->0x%lx\n", debugstr_w(path), lpFindFile, bBindCtx, + ppidl, ppidl ? *ppidl : NULL, + prgfInOut, prgfInOut ? *prgfInOut : 0); - if (!lpszPath) return NULL; + ret = SHGetDesktopFolder(&pSF); + if (FAILED(ret)) + { + return ret; + } - hFile = FindFirstFileA(lpszPath, &stffile); + if (lpFindFile || bBindCtx) + ret = FileSystemBindData_Constructor(lpFindFile, &pBC); - if ( hFile != INVALID_HANDLE_VALUE ) + if (SUCCEEDED(ret)) { - if (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - pidl = _ILCreateFolder (&stffile); - } - else - { - pidl = _ILCreateValue (&stffile); - } - FindClose (hFile); + ret = IShellFolder_ParseDisplayName(pSF, 0, pBC, (LPOLESTR)path, NULL, ppidl, prgfInOut); + } + + if (pBC) + { + IBindCtx_Release(pBC); + pBC = NULL; } + + IShellFolder_Release(pSF); + + if (!SUCCEEDED(ret) && ppidl) + *ppidl = NULL; + + TRACE("%s %p 0x%lx\n", debugstr_w(path), ppidl ? *ppidl : NULL, prgfInOut ? *prgfInOut : 0); + + return ret; +} + +/************************************************************************* + * SHSimpleIDListFromPath [SHELL32.162] + * + * Creates a simple ItemIDList from a path and returns it. This function + * does not fail on non-existing paths. + * + * PARAMS + * path [I] path to parse and convert into an ItemIDList + * + * RETURNS + * the newly created simple ItemIDList + * + * NOTES + * Simple in the name does not mean a relative ItemIDList but rather a + * fully qualified list, where only the file name is filled in and the + * directory flag for those ItemID elements this is known about, eg. + * it is not the last element in the ItemIDList or the actual directory + * exists on disk. + * exported by ordinal. + */ +LPITEMIDLIST WINAPI SHSimpleIDListFromPathA(LPCSTR lpszPath) +{ + LPITEMIDLIST pidl = NULL; + LPWSTR wPath = NULL; + + TRACE("%s\n", debugstr_a(lpszPath)); + + SHELL32_StrAtoW(&wPath, lpszPath); + + _ILParsePathW(wPath, NULL, TRUE, &pidl, NULL); + SHELL32_StrFree(wPath); + TRACE("%s %p\n", debugstr_a(lpszPath), pidl); return pidl; } -LPITEMIDLIST WINAPI SHSimpleIDListFromPathW (LPCWSTR lpszPath) + +LPITEMIDLIST WINAPI SHSimpleIDListFromPathW(LPCWSTR lpszPath) { - char lpszTemp[MAX_PATH]; - TRACE("path=%s\n",debugstr_w(lpszPath)); + LPITEMIDLIST pidl = NULL; - if (!WideCharToMultiByte( CP_ACP, 0, lpszPath, -1, lpszTemp, sizeof(lpszTemp), NULL, NULL )) - lpszTemp[sizeof(lpszTemp)-1] = 0; + TRACE("%s\n", debugstr_w(lpszPath)); - return SHSimpleIDListFromPathA (lpszTemp); + _ILParsePathW(lpszPath, NULL, TRUE, &pidl, NULL); + TRACE("%s %p\n", debugstr_w(lpszPath), pidl); + return pidl; } -LPITEMIDLIST WINAPI SHSimpleIDListFromPathAW (LPCVOID lpszPath) +LPITEMIDLIST WINAPI SHSimpleIDListFromPathAW(LPCVOID lpszPath) { if ( SHELL_OsIsUnicode()) return SHSimpleIDListFromPathW (lpszPath); @@ -958,7 +1033,7 @@ { WIN32_FIND_DATAA * pfd = dest; - if ( len < sizeof (WIN32_FIND_DATAA)) return E_INVALIDARG; + if (len < (int)sizeof(WIN32_FIND_DATAA)) return E_INVALIDARG; ZeroMemory(pfd, sizeof (WIN32_FIND_DATAA)); _ILGetFileDateTime( pidl, &(pfd->ftLastWriteTime)); @@ -998,7 +1073,7 @@ { WIN32_FIND_DATAW * pfd = dest; - if ( len < sizeof (WIN32_FIND_DATAW)) return E_INVALIDARG; + if (len < (int)sizeof(WIN32_FIND_DATAW)) return E_INVALIDARG; ZeroMemory(pfd, sizeof (WIN32_FIND_DATAA)); _ILGetFileDateTime( pidl, &(pfd->ftLastWriteTime)); @@ -1090,6 +1165,18 @@ } /************************************************************************* + * SHGetPathFromIDList [SHELL32.@][NT 4.0: SHELL32.219] + */ +BOOL WINAPI SHGetPathFromIDListAW(LPCITEMIDLIST pidl,LPVOID pszPath) +{ + TRACE_(shell)("(pidl=%p,%p)\n",pidl,pszPath); + + if (SHELL_OsIsUnicode()) + return SHGetPathFromIDListW(pidl,pszPath); + return SHGetPathFromIDListA(pidl,pszPath); +} + +/************************************************************************* * SHBindToParent [shell version 5.0] */ HRESULT WINAPI SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCITEMIDLIST *ppidlLast) @@ -1134,18 +1221,6 @@ TRACE_(shell)("-- psf=%p pidl=%p ret=0x%08lx\n", *ppv, (ppidlLast)?*ppidlLast:NULL, hr); return hr; -} - -/************************************************************************* - * SHGetPathFromIDList [SHELL32.@][NT 4.0: SHELL32.219] - */ -BOOL WINAPI SHGetPathFromIDListAW(LPCITEMIDLIST pidl,LPVOID pszPath) -{ - TRACE_(shell)("(pidl=%p,%p)\n",pidl,pszPath); - - if (SHELL_OsIsUnicode()) - return SHGetPathFromIDListW(pidl,pszPath); - return SHGetPathFromIDListA(pidl,pszPath); } /************************************************************************** =================================================================== RCS file: /home/wine/wine/dlls/shell32/shell32_main.h,v retrieving revision 1.70 diff -u -r1.70 shell32_main.h --- dlls/shell32/shell32_main.h 9 Sep 2003 19:32:36 -0000 1.70 +++ dlls/shell32/shell32_main.h 11 Sep 2003 18:03:19 -0000 @@ -211,6 +211,18 @@ WideCharToMultiByte(CP_ACP, 0, source, -1, *target, len, NULL, NULL); } +inline static void SHELL32_StrAtoW(WCHAR ** target, const char * source) +{ + int len = MultiByteToWideChar(CP_ACP, 0, source, -1, NULL, 0); + *target = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, source, -1, *target, len); +} + +inline static void SHELL32_StrFree(LPVOID pv) +{ + HeapFree(GetProcessHeap(), 0, pv); +} + /* handle conversions */ #define HICON_16(h32) (LOWORD(h32)) #define HICON_32(h16) ((HICON)(ULONG_PTR)(h16))