ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pidl.cpp
Go to the documentation of this file.
00001 /*
00002  *    pidl Handling
00003  *
00004  *    Copyright 1998    Juergen Schmied
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  *
00020  * NOTES
00021  *  a pidl == NULL means desktop and is legal
00022  *
00023  */
00024 
00025 #include <precomp.h>
00026 
00027 WINE_DEFAULT_DEBUG_CHANNEL(pidl);
00028 WINE_DECLARE_DEBUG_CHANNEL(shell);
00029 
00030 /* from comctl32.dll */
00031 EXTERN_C LPVOID WINAPI Alloc(INT);
00032 EXTERN_C BOOL WINAPI Free(LPVOID);
00033 
00034 static LPSTR _ILGetSTextPointer(LPCITEMIDLIST pidl);
00035 static LPWSTR _ILGetTextPointerW(LPCITEMIDLIST pidl);
00036 
00037 /*************************************************************************
00038  * ILGetDisplayNameExA        [SHELL32.186]
00039  *
00040  * Retrieves the display name of an ItemIDList
00041  *
00042  * PARAMS
00043  *  psf        [I]   Shell Folder to start with, if NULL the desktop is used
00044  *  pidl       [I]   ItemIDList relative to the psf to get the display name for
00045  *  path       [O]   Filled in with the display name, assumed to be at least MAX_PATH long
00046  *  type       [I]   Type of display name to retrieve
00047  *                    0 = SHGDN_FORPARSING | SHGDN_FORADDRESSBAR uses always the desktop as root
00048  *                    1 = SHGDN_NORMAL relative to the root folder
00049  *                    2 = SHGDN_INFOLDER relative to the root folder, only the last name
00050  *
00051  * RETURNS
00052  *  True if the display name could be retrieved successfully, False otherwise
00053  */
00054 static BOOL ILGetDisplayNameExA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPSTR path, DWORD type)
00055 {
00056     BOOL ret = FALSE;
00057     WCHAR wPath[MAX_PATH];
00058 
00059     TRACE("%p %p %p %d\n", psf, pidl, path, type);
00060 
00061     if (!pidl || !path)
00062         return FALSE;
00063 
00064     ret = ILGetDisplayNameExW(psf, pidl, wPath, type);
00065     WideCharToMultiByte(CP_ACP, 0, wPath, -1, path, MAX_PATH, NULL, NULL);
00066     TRACE("%p %p %s\n", psf, pidl, debugstr_a(path));
00067 
00068     return ret;
00069 }
00070 
00071 BOOL WINAPI ILGetDisplayNameExW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPWSTR path, DWORD type)
00072 {
00073     CComPtr<IShellFolder>        psfParent;
00074     LPSHELLFOLDER lsf = psf;
00075     HRESULT ret = NO_ERROR;
00076     LPCITEMIDLIST pidllast;
00077     STRRET strret;
00078     DWORD flag;
00079 
00080     TRACE("%p %p %p %d\n", psf, pidl, path, type);
00081 
00082     if (!pidl || !path)
00083         return FALSE;
00084 
00085     if (!lsf)
00086     {
00087         ret = SHGetDesktopFolder(&lsf);
00088         if (FAILED(ret))
00089             return FALSE;
00090     }
00091 
00092     if (type <= 2)
00093     {
00094         switch (type)
00095         {
00096             case ILGDN_FORPARSING:
00097                 flag = SHGDN_FORPARSING | SHGDN_FORADDRESSBAR;
00098                 break;
00099             case ILGDN_NORMAL:
00100                 flag = SHGDN_NORMAL;
00101                 break;
00102             case ILGDN_INFOLDER:
00103                 flag = SHGDN_INFOLDER;
00104                 break;
00105             default:
00106                 FIXME("Unknown type parameter = %x\n", type);
00107                 flag = SHGDN_FORPARSING | SHGDN_FORADDRESSBAR;
00108                 break;
00109         }
00110         if (!*(const WORD*)pidl || type == ILGDN_FORPARSING)
00111         {
00112             ret = lsf->GetDisplayNameOf(pidl, flag, &strret);
00113             if (SUCCEEDED(ret))
00114             {
00115                 if(!StrRetToStrNW(path, MAX_PATH, &strret, pidl))
00116                     ret = E_FAIL;
00117             }
00118         }
00119         else
00120         {
00121             ret = SHBindToParent(pidl, IID_IShellFolder, (LPVOID*)&psfParent, &pidllast);
00122             if (SUCCEEDED(ret))
00123             {
00124                 ret = psfParent->GetDisplayNameOf(pidllast, flag, &strret);
00125                 if (SUCCEEDED(ret))
00126                 {
00127                     if(!StrRetToStrNW(path, MAX_PATH, &strret, pidllast))
00128                         ret = E_FAIL;
00129                 }
00130             }
00131         }
00132     }
00133 
00134     TRACE("%p %p %s\n", psf, pidl, debugstr_w(path));
00135 
00136     if (!psf)
00137         lsf->Release();
00138     return SUCCEEDED(ret);
00139 }
00140 
00141 /*************************************************************************
00142  * ILGetDisplayNameEx        [SHELL32.186]
00143  */
00144 BOOL WINAPI ILGetDisplayNameEx(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPVOID path, DWORD type)
00145 {
00146     TRACE_(shell)("%p %p %p %d\n", psf, pidl, path, type);
00147 
00148     if (SHELL_OsIsUnicode())
00149         return ILGetDisplayNameExW(psf, pidl, (LPWSTR)path, type);
00150     return ILGetDisplayNameExA(psf, pidl, (LPSTR)path, type);
00151 }
00152 
00153 /*************************************************************************
00154  * ILGetDisplayName            [SHELL32.15]
00155  */
00156 BOOL WINAPI ILGetDisplayName(LPCITEMIDLIST pidl, LPVOID path)
00157 {
00158     TRACE_(shell)("%p %p\n", pidl, path);
00159 
00160     if (SHELL_OsIsUnicode())
00161         return ILGetDisplayNameExW(NULL, pidl, (LPWSTR)path, ILGDN_FORPARSING);
00162     return ILGetDisplayNameExA(NULL, pidl, (LPSTR)path, ILGDN_FORPARSING);
00163 }
00164 
00165 /*************************************************************************
00166  * ILFindLastID [SHELL32.16]
00167  *
00168  * NOTES
00169  *   observed: pidl=Desktop return=pidl
00170  */
00171 LPITEMIDLIST WINAPI ILFindLastID(LPCITEMIDLIST pidl)
00172 {
00173     LPCITEMIDLIST   pidlLast = pidl;
00174 
00175     TRACE("(pidl=%p)\n", pidl);
00176 
00177     if (!pidl)
00178         return NULL;
00179 
00180     while (pidl->mkid.cb)
00181     {
00182         pidlLast = pidl;
00183         pidl = ILGetNext(pidl);
00184     }
00185     return (LPITEMIDLIST)pidlLast;
00186 }
00187 
00188 /*************************************************************************
00189  * ILRemoveLastID [SHELL32.17]
00190  *
00191  * NOTES
00192  *   when pidl=Desktop return=FALSE
00193  */
00194 BOOL WINAPI ILRemoveLastID(LPITEMIDLIST pidl)
00195 {
00196     TRACE_(shell)("pidl=%p\n", pidl);
00197 
00198     if (!pidl || !pidl->mkid.cb)
00199         return 0;
00200     ILFindLastID(pidl)->mkid.cb = 0;
00201     return 1;
00202 }
00203 
00204 /*************************************************************************
00205  * ILClone [SHELL32.18]
00206  *
00207  * NOTES
00208  *    duplicate an idlist
00209  */
00210 LPITEMIDLIST WINAPI ILClone (LPCITEMIDLIST pidl)
00211 {
00212     DWORD    len;
00213     LPITEMIDLIST  newpidl;
00214 
00215     if (!pidl)
00216         return NULL;
00217 
00218     len = ILGetSize(pidl);
00219     newpidl = (LPITEMIDLIST)SHAlloc(len);
00220     if (newpidl)
00221         memcpy(newpidl, pidl, len);
00222 
00223     TRACE("pidl=%p newpidl=%p\n", pidl, newpidl);
00224     pdump(pidl);
00225 
00226     return newpidl;
00227 }
00228 
00229 /*************************************************************************
00230  * ILCloneFirst [SHELL32.19]
00231  *
00232  * NOTES
00233  *  duplicates the first idlist of a complex pidl
00234  */
00235 LPITEMIDLIST WINAPI ILCloneFirst(LPCITEMIDLIST pidl)
00236 {
00237     DWORD len;
00238     LPITEMIDLIST pidlNew = NULL;
00239 
00240     TRACE("pidl=%p\n", pidl);
00241     pdump(pidl);
00242 
00243     if (pidl)
00244     {
00245         len = pidl->mkid.cb;
00246         pidlNew = (LPITEMIDLIST)SHAlloc(len + 2);
00247         if (pidlNew)
00248         {
00249             memcpy(pidlNew, pidl, len + 2);    /* 2 -> mind a desktop pidl */
00250 
00251             if (len)
00252                 ILGetNext(pidlNew)->mkid.cb = 0x00;
00253         }
00254     }
00255     TRACE("-- newpidl=%p\n", pidlNew);
00256 
00257     return pidlNew;
00258 }
00259 
00260 /*************************************************************************
00261  * ILLoadFromStream (SHELL32.26)
00262  *
00263  * NOTES
00264  *   the first two bytes are the len, the pidl is following then
00265  */
00266 HRESULT WINAPI ILLoadFromStream (IStream * pStream, LPITEMIDLIST * ppPidl)
00267 {
00268     WORD        wLen = 0;
00269     DWORD       dwBytesRead;
00270     HRESULT     ret = E_FAIL;
00271 
00272 
00273     TRACE_(shell)("%p %p\n", pStream ,  ppPidl);
00274 
00275     SHFree(*ppPidl);
00276     *ppPidl = NULL;
00277 
00278     pStream->AddRef ();
00279 
00280     if (SUCCEEDED(pStream->Read(&wLen, 2, &dwBytesRead)))
00281     {
00282         TRACE("PIDL length is %d\n", wLen);
00283         if (wLen != 0)
00284         {
00285             *ppPidl = (LPITEMIDLIST)SHAlloc(wLen);
00286             if (SUCCEEDED(pStream->Read(*ppPidl , wLen, &dwBytesRead)))
00287             {
00288                 TRACE("Stream read OK\n");
00289                 ret = S_OK;
00290             }
00291             else
00292             {
00293                 WARN("reading pidl failed\n");
00294                 SHFree(*ppPidl);
00295                 *ppPidl = NULL;
00296             }
00297         }
00298         else
00299         {
00300             *ppPidl = NULL;
00301             ret = S_OK;
00302         }
00303     }
00304 
00305     /* we are not yet fully compatible */
00306     if (*ppPidl && !pcheck(*ppPidl))
00307     {
00308         WARN("Check failed\n");
00309         SHFree(*ppPidl);
00310         *ppPidl = NULL;
00311     }
00312 
00313     pStream->Release ();
00314     TRACE("done\n");
00315     return ret;
00316 }
00317 
00318 /*************************************************************************
00319  * ILSaveToStream (SHELL32.27)
00320  *
00321  * NOTES
00322  *   the first two bytes are the len, the pidl is following then
00323  */
00324 HRESULT WINAPI ILSaveToStream (IStream * pStream, LPCITEMIDLIST pPidl)
00325 {
00326     WORD        wLen = 0;
00327     HRESULT        ret = E_FAIL;
00328 
00329     TRACE_(shell)("%p %p\n", pStream, pPidl);
00330 
00331     pStream->AddRef ();
00332 
00333     wLen = ILGetSize(pPidl);
00334 
00335     if (SUCCEEDED(pStream->Write(&wLen, 2, NULL)))
00336     {
00337         if (SUCCEEDED(pStream->Write(pPidl, wLen, NULL)))
00338             ret = S_OK;
00339     }
00340     pStream->Release ();
00341 
00342     return ret;
00343 }
00344 
00345 /*************************************************************************
00346  * SHILCreateFromPath        [SHELL32.28]
00347  *
00348  * Create an ItemIDList from a path
00349  *
00350  * PARAMS
00351  *  path       [I]
00352  *  ppidl      [O]
00353  *  attributes [I/O] requested attributes on call and actual attributes when
00354  *                   the function returns
00355  *
00356  * RETURNS
00357  *  NO_ERROR if successful, or an OLE errer code otherwise
00358  *
00359  * NOTES
00360  *  Wrapper for IShellFolder_ParseDisplayName().
00361  */
00362 HRESULT WINAPI SHILCreateFromPathA(LPCSTR path, LPITEMIDLIST * ppidl, DWORD * attributes)
00363 {
00364     WCHAR lpszDisplayName[MAX_PATH];
00365 
00366     TRACE_(shell)("%s %p 0x%08x\n", path, ppidl, attributes ? *attributes : 0);
00367 
00368     if (!MultiByteToWideChar(CP_ACP, 0, path, -1, lpszDisplayName, MAX_PATH))
00369         lpszDisplayName[MAX_PATH-1] = 0;
00370 
00371     return SHILCreateFromPathW(lpszDisplayName, ppidl, attributes);
00372 }
00373 
00374 HRESULT WINAPI SHILCreateFromPathW(LPCWSTR path, LPITEMIDLIST * ppidl, DWORD * attributes)
00375 {
00376     CComPtr<IShellFolder>        sf;
00377     DWORD pchEaten;
00378     HRESULT ret = E_FAIL;
00379 
00380     TRACE_(shell)("%s %p 0x%08x\n", debugstr_w(path), ppidl, attributes ? *attributes : 0);
00381 
00382     if (SUCCEEDED (SHGetDesktopFolder(&sf)))
00383         ret = sf->ParseDisplayName(0, NULL, (LPWSTR)path, &pchEaten, ppidl, attributes);
00384     return ret;
00385 }
00386 
00387 EXTERN_C HRESULT WINAPI SHILCreateFromPathAW (LPCVOID path, LPITEMIDLIST * ppidl, DWORD * attributes)
00388 {
00389     if ( SHELL_OsIsUnicode())
00390         return SHILCreateFromPathW ((LPCWSTR)path, ppidl, attributes);
00391     return SHILCreateFromPathA ((LPCSTR)path, ppidl, attributes);
00392 }
00393 
00394 /*************************************************************************
00395  * SHCloneSpecialIDList      [SHELL32.89]
00396  *
00397  * Create an ItemIDList to one of the special folders.
00398 
00399  * PARAMS
00400  *  hwndOwner    [in]
00401  *  nFolder      [in]    CSIDL_xxxxx
00402  *  fCreate      [in]    Create folder if it does not exist
00403  *
00404  * RETURNS
00405  *  Success: The newly created pidl
00406  *  Failure: NULL, if inputs are invalid.
00407  *
00408  * NOTES
00409  *  exported by ordinal.
00410  *  Caller is responsible for deallocating the returned ItemIDList with the
00411  *  shells IMalloc interface, aka ILFree.
00412  */
00413 LPITEMIDLIST WINAPI SHCloneSpecialIDList(HWND hwndOwner, int nFolder, BOOL fCreate)
00414 {
00415     LPITEMIDLIST ppidl;
00416     TRACE_(shell)("(hwnd=%p,csidl=0x%x,%s).\n", hwndOwner, nFolder, fCreate ? "T" : "F");
00417 
00418     if (fCreate)
00419         nFolder |= CSIDL_FLAG_CREATE;
00420 
00421     SHGetSpecialFolderLocation(hwndOwner, nFolder, &ppidl);
00422     return ppidl;
00423 }
00424 
00425 /*************************************************************************
00426  * ILGlobalClone             [SHELL32.20]
00427  *
00428  * Clones an ItemIDList using Alloc.
00429  *
00430  * PARAMS
00431  *  pidl       [I]   ItemIDList to clone
00432  *
00433  * RETURNS
00434  *  Newly allocated ItemIDList.
00435  *
00436  * NOTES
00437  *  exported by ordinal.
00438  */
00439 LPITEMIDLIST WINAPI ILGlobalClone(LPCITEMIDLIST pidl)
00440 {
00441     DWORD    len;
00442     LPITEMIDLIST  newpidl;
00443 
00444     if (!pidl)
00445         return NULL;
00446 
00447     len = ILGetSize(pidl);
00448     newpidl = (LPITEMIDLIST)Alloc(len);
00449     if (newpidl)
00450         memcpy(newpidl, pidl, len);
00451 
00452     TRACE("pidl=%p newpidl=%p\n", pidl, newpidl);
00453     pdump(pidl);
00454 
00455     return newpidl;
00456 }
00457 
00458 /*************************************************************************
00459  * ILIsEqual [SHELL32.21]
00460  *
00461  */
00462 BOOL WINAPI ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
00463 {
00464     char    szData1[MAX_PATH];
00465     char    szData2[MAX_PATH];
00466 
00467     LPCITEMIDLIST pidltemp1 = pidl1;
00468     LPCITEMIDLIST pidltemp2 = pidl2;
00469 
00470     TRACE("pidl1=%p pidl2=%p\n", pidl1, pidl2);
00471 
00472     /*
00473      * Explorer reads from registry directly (StreamMRU),
00474      * so we can only check here
00475      */
00476     if (!pcheck(pidl1) || !pcheck (pidl2))
00477         return FALSE;
00478 
00479     pdump (pidl1);
00480     pdump (pidl2);
00481 
00482     if (!pidl1 || !pidl2)
00483         return FALSE;
00484 
00485     while (pidltemp1->mkid.cb && pidltemp2->mkid.cb)
00486     {
00487         _ILSimpleGetText(pidltemp1, szData1, MAX_PATH);
00488         _ILSimpleGetText(pidltemp2, szData2, MAX_PATH);
00489 
00490         if (strcmp( szData1, szData2 ))
00491             return FALSE;
00492 
00493         pidltemp1 = ILGetNext(pidltemp1);
00494         pidltemp2 = ILGetNext(pidltemp2);
00495     }
00496 
00497     if (!pidltemp1->mkid.cb && !pidltemp2->mkid.cb)
00498         return TRUE;
00499 
00500     return FALSE;
00501 }
00502 
00503 /*************************************************************************
00504  * ILIsParent                [SHELL32.23]
00505  *
00506  * Verifies that pidlParent is indeed the (immediate) parent of pidlChild.
00507  *
00508  * PARAMS
00509  *  pidlParent [I]
00510  *  pidlChild  [I]
00511  *  bImmediate [I]   only return true if the parent is the direct parent
00512  *                   of the child
00513  *
00514  * RETURNS
00515  *  True if the parent ItemIDlist is a complete part of the child ItemIdList,
00516  *  False otherwise.
00517  *
00518  * NOTES
00519  *  parent = a/b, child = a/b/c -> true, c is in folder a/b
00520  *  child = a/b/c/d -> false if bImmediate is true, d is not in folder a/b
00521  *  child = a/b/c/d -> true if bImmediate is false, d is in a subfolder of a/b
00522  */
00523 BOOL WINAPI ILIsParent(LPCITEMIDLIST pidlParent, LPCITEMIDLIST pidlChild, BOOL bImmediate)
00524 {
00525     char    szData1[MAX_PATH];
00526     char    szData2[MAX_PATH];
00527     LPCITEMIDLIST pParent = pidlParent;
00528     LPCITEMIDLIST pChild = pidlChild;
00529 
00530     TRACE("%p %p %x\n", pidlParent, pidlChild, bImmediate);
00531 
00532     if (!pParent || !pChild)
00533         return FALSE;
00534 
00535     while (pParent->mkid.cb && pChild->mkid.cb)
00536     {
00537         _ILSimpleGetText(pParent, szData1, MAX_PATH);
00538         _ILSimpleGetText(pChild, szData2, MAX_PATH);
00539 
00540         if (strcmp( szData1, szData2 ))
00541             return FALSE;
00542 
00543         pParent = ILGetNext(pParent);
00544         pChild = ILGetNext(pChild);
00545     }
00546 
00547     /* child shorter or has equal length to parent */
00548     if (pParent->mkid.cb || !pChild->mkid.cb)
00549         return FALSE;
00550 
00551     /* not immediate descent */
00552     if ( ILGetNext(pChild)->mkid.cb && bImmediate)
00553         return FALSE;
00554 
00555     return TRUE;
00556 }
00557 
00558 /*************************************************************************
00559  * ILFindChild               [SHELL32.24]
00560  *
00561  *  Compares elements from pidl1 and pidl2.
00562  *
00563  * PARAMS
00564  *  pidl1      [I]
00565  *  pidl2      [I]
00566  *
00567  * RETURNS
00568  *  pidl1 is desktop      pidl2
00569  *  pidl1 shorter pidl2   pointer to first different element of pidl2
00570  *                        if there was at least one equal element
00571  *  pidl2 shorter pidl1   0
00572  *  pidl2 equal pidl1     pointer to last 0x00-element of pidl2
00573  *
00574  * NOTES
00575  *  exported by ordinal.
00576  */
00577 LPITEMIDLIST WINAPI ILFindChild(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
00578 {
00579     char    szData1[MAX_PATH];
00580     char    szData2[MAX_PATH];
00581 
00582     LPCITEMIDLIST pidltemp1 = pidl1;
00583     LPCITEMIDLIST pidltemp2 = pidl2;
00584     LPCITEMIDLIST ret = NULL;
00585 
00586     TRACE("pidl1=%p pidl2=%p\n", pidl1, pidl2);
00587 
00588     /* explorer reads from registry directly (StreamMRU),
00589        so we can only check here */
00590     if ((!pcheck (pidl1)) || (!pcheck (pidl2)))
00591         return FALSE;
00592 
00593     pdump (pidl1);
00594     pdump (pidl2);
00595 
00596     if (_ILIsDesktop(pidl1))
00597     {
00598         ret = pidl2;
00599     }
00600     else
00601     {
00602         while (pidltemp1->mkid.cb && pidltemp2->mkid.cb)
00603         {
00604             _ILSimpleGetText(pidltemp1, szData1, MAX_PATH);
00605             _ILSimpleGetText(pidltemp2, szData2, MAX_PATH);
00606 
00607             if (strcmp(szData1, szData2))
00608                 break;
00609 
00610             pidltemp1 = ILGetNext(pidltemp1);
00611             pidltemp2 = ILGetNext(pidltemp2);
00612             ret = pidltemp2;
00613         }
00614 
00615         if (pidltemp1->mkid.cb)
00616             ret = NULL; /* elements of pidl1 left*/
00617     }
00618     TRACE_(shell)("--- %p\n", ret);
00619     return (LPITEMIDLIST)ret; /* pidl 1 is shorter */
00620 }
00621 
00622 /*************************************************************************
00623  * ILCombine                 [SHELL32.25]
00624  *
00625  * Concatenates two complex ItemIDLists.
00626  *
00627  * PARAMS
00628  *  pidl1      [I]   first complex ItemIDLists
00629  *  pidl2      [I]   complex ItemIDLists to append
00630  *
00631  * RETURNS
00632  *  if both pidl's == NULL      NULL
00633  *  if pidl1 == NULL            cloned pidl2
00634  *  if pidl2 == NULL            cloned pidl1
00635  *  otherwise new pidl with pidl2 appended to pidl1
00636  *
00637  * NOTES
00638  *  exported by ordinal.
00639  *  Does not destroy the passed in ItemIDLists!
00640  */
00641 LPITEMIDLIST WINAPI ILCombine(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
00642 {
00643     DWORD    len1, len2;
00644     LPITEMIDLIST  pidlNew;
00645 
00646     TRACE("pidl=%p pidl=%p\n", pidl1, pidl2);
00647 
00648     if (!pidl1 && !pidl2) return NULL;
00649 
00650     pdump (pidl1);
00651     pdump (pidl2);
00652 
00653     if (!pidl1)
00654     {
00655         pidlNew = ILClone(pidl2);
00656         return pidlNew;
00657     }
00658 
00659     if (!pidl2)
00660     {
00661         pidlNew = ILClone(pidl1);
00662         return pidlNew;
00663     }
00664 
00665     len1  = ILGetSize(pidl1) - 2;
00666     len2  = ILGetSize(pidl2);
00667     pidlNew  = (LPITEMIDLIST)SHAlloc(len1 + len2);
00668 
00669     if (pidlNew)
00670     {
00671         memcpy(pidlNew, pidl1, len1);
00672         memcpy(((BYTE *)pidlNew) + len1, pidl2, len2);
00673     }
00674 
00675     /*  TRACE(pidl,"--new pidl=%p\n",pidlNew);*/
00676     return pidlNew;
00677 }
00678 
00679 /*************************************************************************
00680  *  SHGetRealIDL [SHELL32.98]
00681  *
00682  * NOTES
00683  */
00684 HRESULT WINAPI SHGetRealIDL(LPSHELLFOLDER lpsf, LPCITEMIDLIST pidlSimple, LPITEMIDLIST *pidlReal)
00685 {
00686     CComPtr<IDataObject>        pDataObj;
00687     HRESULT hr;
00688 
00689     hr = lpsf->GetUIObjectOf(0, 1, &pidlSimple,
00690                              IID_IDataObject, 0, (LPVOID*)&pDataObj);
00691     if (SUCCEEDED(hr))
00692     {
00693         STGMEDIUM medium;
00694         FORMATETC fmt;
00695 
00696         fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLIST);
00697         fmt.ptd = NULL;
00698         fmt.dwAspect = DVASPECT_CONTENT;
00699         fmt.lindex = -1;
00700         fmt.tymed = TYMED_HGLOBAL;
00701 
00702         hr = pDataObj->GetData(&fmt, &medium);
00703 
00704         if (SUCCEEDED(hr))
00705         {
00706             /*assert(pida->cidl==1);*/
00707             LPIDA pida = (LPIDA)GlobalLock(medium.hGlobal);
00708 
00709             LPCITEMIDLIST pidl_folder = (LPCITEMIDLIST) ((LPBYTE)pida + pida->aoffset[0]);
00710             LPCITEMIDLIST pidl_child = (LPCITEMIDLIST) ((LPBYTE)pida + pida->aoffset[1]);
00711 
00712             *pidlReal = ILCombine(pidl_folder, pidl_child);
00713 
00714             if (!*pidlReal)
00715                 hr = E_OUTOFMEMORY;
00716 
00717             GlobalUnlock(medium.hGlobal);
00718             GlobalFree(medium.hGlobal);
00719         }
00720     }
00721 
00722     return hr;
00723 }
00724 
00725 /*************************************************************************
00726  *  SHLogILFromFSIL [SHELL32.95]
00727  *
00728  * NOTES
00729  *  pild = CSIDL_DESKTOP    ret = 0
00730  *  pild = CSIDL_DRIVES     ret = 0
00731  */
00732 EXTERN_C LPITEMIDLIST WINAPI SHLogILFromFSIL(LPITEMIDLIST pidl)
00733 {
00734     FIXME("(pidl=%p)\n", pidl);
00735 
00736     pdump(pidl);
00737 
00738     return 0;
00739 }
00740 
00741 /*************************************************************************
00742  * ILGetSize                 [SHELL32.152]
00743  *
00744  * Gets the byte size of an ItemIDList including zero terminator
00745  *
00746  * PARAMS
00747  *  pidl       [I]   ItemIDList
00748  *
00749  * RETURNS
00750  *  size of pidl in bytes
00751  *
00752  * NOTES
00753  *  exported by ordinal
00754  */
00755 UINT WINAPI ILGetSize(LPCITEMIDLIST pidl)
00756 {
00757     LPCSHITEMID si = &(pidl->mkid);
00758     UINT len = 0;
00759 
00760     if (pidl)
00761     {
00762         while (si->cb)
00763         {
00764             len += si->cb;
00765             si  = (LPCSHITEMID)(((const BYTE*)si) + si->cb);
00766         }
00767         len += 2;
00768     }
00769     TRACE("pidl=%p size=%u\n", pidl, len);
00770     return len;
00771 }
00772 
00773 /*************************************************************************
00774  * ILGetNext                 [SHELL32.153]
00775  *
00776  * Gets the next ItemID of an ItemIDList
00777  *
00778  * PARAMS
00779  *  pidl       [I]   ItemIDList
00780  *
00781  * RETURNS
00782  *  null -> null
00783  *  desktop -> null
00784  *  simple pidl -> pointer to 0x0000 element
00785  *
00786  * NOTES
00787  *  exported by ordinal.
00788  */
00789 LPITEMIDLIST WINAPI ILGetNext(LPCITEMIDLIST pidl)
00790 {
00791     WORD len;
00792 
00793     TRACE("%p\n", pidl);
00794 
00795     if (pidl)
00796     {
00797         len =  pidl->mkid.cb;
00798         if (len)
00799         {
00800             pidl = (LPCITEMIDLIST) (((const BYTE*)pidl) + len);
00801             TRACE("-- %p\n", pidl);
00802             return (LPITEMIDLIST)pidl;
00803         }
00804     }
00805     return NULL;
00806 }
00807 
00808 /*************************************************************************
00809  * ILAppend                  [SHELL32.154]
00810  *
00811  * Adds the single ItemID item to the ItemIDList indicated by pidl.
00812  * If bEnd is FALSE, inserts the item in the front of the list,
00813  * otherwise it adds the item to the end. (???)
00814  *
00815  * PARAMS
00816  *  pidl       [I]   ItemIDList to extend
00817  *  item       [I]   ItemID to prepend/append
00818  *  bEnd       [I]   Indicates if the item should be appended
00819  *
00820  * NOTES
00821  *  Destroys the passed in idlist! (???)
00822  */
00823 EXTERN_C LPITEMIDLIST WINAPI ILAppend(LPITEMIDLIST pidl, LPCITEMIDLIST item, BOOL bEnd)
00824 {
00825     LPITEMIDLIST idlRet;
00826 
00827     WARN("(pidl=%p,pidl=%p,%08u)semi-stub\n", pidl, item, bEnd);
00828 
00829     pdump (pidl);
00830     pdump (item);
00831 
00832     if (_ILIsDesktop(pidl))
00833     {
00834         idlRet = ILClone(item);
00835         SHFree (pidl);
00836         return idlRet;
00837     }
00838 
00839     if (bEnd)
00840         idlRet = ILCombine(pidl, item);
00841     else
00842         idlRet = ILCombine(item, pidl);
00843 
00844     SHFree(pidl);
00845     return idlRet;
00846 }
00847 
00848 /*************************************************************************
00849  * ILFree                    [SHELL32.155]
00850  *
00851  * Frees memory (if not NULL) allocated by SHMalloc allocator
00852  *
00853  * PARAMS
00854  *  pidl         [I]
00855  *
00856  * RETURNS
00857  *  Nothing
00858  *
00859  * NOTES
00860  *  exported by ordinal
00861  */
00862 void WINAPI ILFree(LPITEMIDLIST pidl)
00863 {
00864     TRACE("(pidl=%p)\n", pidl);
00865     SHFree(pidl);
00866 }
00867 
00868 /*************************************************************************
00869  * ILGlobalFree              [SHELL32.156]
00870  *
00871  * Frees memory (if not NULL) allocated by Alloc allocator
00872  *
00873  * PARAMS
00874  *  pidl         [I]
00875  *
00876  * RETURNS
00877  *  Nothing
00878  *
00879  * NOTES
00880  *  exported by ordinal.
00881  */
00882 void WINAPI ILGlobalFree( LPITEMIDLIST pidl)
00883 {
00884     TRACE("%p\n", pidl);
00885 
00886     Free(pidl);
00887 }
00888 
00889 /*************************************************************************
00890  * ILCreateFromPathA         [SHELL32.189]
00891  *
00892  * Creates a complex ItemIDList from a path and returns it.
00893  *
00894  * PARAMS
00895  *  path         [I]
00896  *
00897  * RETURNS
00898  *  the newly created complex ItemIDList or NULL if failed
00899  *
00900  * NOTES
00901  *  exported by ordinal.
00902  */
00903 LPITEMIDLIST WINAPI ILCreateFromPathA (LPCSTR path)
00904 {
00905     LPITEMIDLIST pidlnew = NULL;
00906 
00907     TRACE_(shell)("%s\n", debugstr_a(path));
00908 
00909     if (SUCCEEDED(SHILCreateFromPathA(path, &pidlnew, NULL)))
00910         return pidlnew;
00911     return NULL;
00912 }
00913 
00914 /*************************************************************************
00915  * ILCreateFromPathW         [SHELL32.190]
00916  *
00917  * See ILCreateFromPathA.
00918  */
00919 LPITEMIDLIST WINAPI ILCreateFromPathW (LPCWSTR path)
00920 {
00921     LPITEMIDLIST pidlnew = NULL;
00922 
00923     TRACE_(shell)("%s\n", debugstr_w(path));
00924 
00925     if (SUCCEEDED(SHILCreateFromPathW(path, &pidlnew, NULL)))
00926         return pidlnew;
00927     return NULL;
00928 }
00929 
00930 /*************************************************************************
00931  * ILCreateFromPath          [SHELL32.157]
00932  */
00933 EXTERN_C LPITEMIDLIST WINAPI ILCreateFromPathAW (LPCVOID path)
00934 {
00935     if ( SHELL_OsIsUnicode())
00936         return ILCreateFromPathW ((LPCWSTR)path);
00937     return ILCreateFromPathA ((LPCSTR)path);
00938 }
00939 
00940 /*************************************************************************
00941  * _ILParsePathW             [internal]
00942  *
00943  * Creates an ItemIDList from a path and returns it.
00944  *
00945  * PARAMS
00946  *  path         [I]   path to parse and convert into an ItemIDList
00947  *  lpFindFile   [I]   pointer to buffer to initialize the FileSystem
00948  *                     Bind Data object with
00949  *  bBindCtx     [I]   indicates to create a BindContext and assign a
00950  *                     FileSystem Bind Data object
00951  *  ppidl        [O]   the newly create ItemIDList
00952  *  prgfInOut    [I/O] requested attributes on input and actual
00953  *                     attributes on return
00954  *
00955  * RETURNS
00956  *  NO_ERROR on success or an OLE error code
00957  *
00958  * NOTES
00959  *  If either lpFindFile is non-NULL or bBindCtx is TRUE, this function
00960  *  creates a BindContext object and assigns a FileSystem Bind Data object
00961  *  to it, passing the BindContext to IShellFolder_ParseDisplayName. Each
00962  *  IShellFolder uses that FileSystem Bind Data object of the BindContext
00963  *  to pass data about the current path element to the next object. This
00964  *  is used to avoid having to verify the current path element on disk, so
00965  *  that creating an ItemIDList from a nonexistent path still can work.
00966  */
00967 static HRESULT _ILParsePathW(LPCWSTR path, LPWIN32_FIND_DATAW lpFindFile,
00968                              BOOL bBindCtx, LPITEMIDLIST *ppidl, LPDWORD prgfInOut)
00969 {
00970     CComPtr<IShellFolder>    pSF;
00971     CComPtr<IBindCtx>        pBC;
00972     HRESULT ret;
00973 
00974     TRACE("%s %p %d (%p)->%p (%p)->0x%x\n", debugstr_w(path), lpFindFile, bBindCtx,
00975           ppidl, ppidl ? *ppidl : NULL,
00976           prgfInOut, prgfInOut ? *prgfInOut : 0);
00977 
00978     ret = SHGetDesktopFolder(&pSF);
00979     if (FAILED(ret))
00980         return ret;
00981 
00982     if (lpFindFile || bBindCtx)
00983         ret = IFileSystemBindData_Constructor(lpFindFile, &pBC);
00984 
00985     if (SUCCEEDED(ret))
00986     {
00987         ret = pSF->ParseDisplayName(0, pBC, (LPOLESTR)path, NULL, ppidl, prgfInOut);
00988     }
00989 
00990     if (FAILED(ret) && ppidl)
00991         *ppidl = NULL;
00992 
00993     TRACE("%s %p 0x%x\n", debugstr_w(path), ppidl ? *ppidl : NULL, prgfInOut ? *prgfInOut : 0);
00994 
00995     return ret;
00996 }
00997 
00998 /*************************************************************************
00999  * SHSimpleIDListFromPath    [SHELL32.162]
01000  *
01001  * Creates a simple ItemIDList from a path and returns it. This function
01002  * does not fail on nonexistent paths.
01003  *
01004  * PARAMS
01005  *  path         [I]   path to parse and convert into an ItemIDList
01006  *
01007  * RETURNS
01008  *  the newly created simple ItemIDList
01009  *
01010  * NOTES
01011  *  Simple in the name does not mean a relative ItemIDList but rather a
01012  *  fully qualified list, where only the file name is filled in and the
01013  *  directory flag for those ItemID elements this is known about, eg.
01014  *  it is not the last element in the ItemIDList or the actual directory
01015  *  exists on disk.
01016  *  exported by ordinal.
01017  */
01018 LPITEMIDLIST WINAPI SHSimpleIDListFromPathA(LPCSTR lpszPath)
01019 {
01020     LPITEMIDLIST pidl = NULL;
01021     LPWSTR wPath = NULL;
01022     int len;
01023 
01024     TRACE("%s\n", debugstr_a(lpszPath));
01025 
01026     if (lpszPath)
01027     {
01028         len = MultiByteToWideChar(CP_ACP, 0, lpszPath, -1, NULL, 0);
01029         wPath = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
01030         MultiByteToWideChar(CP_ACP, 0, lpszPath, -1, wPath, len);
01031     }
01032 
01033     _ILParsePathW(wPath, NULL, TRUE, &pidl, NULL);
01034 
01035     HeapFree(GetProcessHeap(), 0, wPath);
01036     TRACE("%s %p\n", debugstr_a(lpszPath), pidl);
01037     return pidl;
01038 }
01039 
01040 LPITEMIDLIST WINAPI SHSimpleIDListFromPathW(LPCWSTR lpszPath)
01041 {
01042     LPITEMIDLIST pidl = NULL;
01043 
01044     TRACE("%s\n", debugstr_w(lpszPath));
01045 
01046     _ILParsePathW(lpszPath, NULL, TRUE, &pidl, NULL);
01047     TRACE("%s %p\n", debugstr_w(lpszPath), pidl);
01048     return pidl;
01049 }
01050 
01051 EXTERN_C LPITEMIDLIST WINAPI SHSimpleIDListFromPathAW(LPCVOID lpszPath)
01052 {
01053     if ( SHELL_OsIsUnicode())
01054         return SHSimpleIDListFromPathW ((LPCWSTR)lpszPath);
01055     return SHSimpleIDListFromPathA ((LPCSTR)lpszPath);
01056 }
01057 
01058 /*************************************************************************
01059  * SHGetDataFromIDListA [SHELL32.247]
01060  *
01061  * NOTES
01062  *  the pidl can be a simple one. since we can't get the path out of the pidl
01063  *  we have to take all data from the pidl
01064  */
01065 HRESULT WINAPI SHGetDataFromIDListA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl,
01066                                     int nFormat, LPVOID dest, int len)
01067 {
01068     LPSTR filename, shortname;
01069     WIN32_FIND_DATAA * pfd;
01070 
01071     TRACE_(shell)("sf=%p pidl=%p 0x%04x %p 0x%04x stub\n", psf, pidl, nFormat, dest, len);
01072 
01073     pdump(pidl);
01074     if (!psf || !dest)
01075         return E_INVALIDARG;
01076 
01077     switch (nFormat)
01078     {
01079         case SHGDFIL_FINDDATA:
01080             pfd = (WIN32_FIND_DATAA *)dest;
01081 
01082             if (_ILIsDrive(pidl) || _ILIsSpecialFolder(pidl))
01083                 return E_INVALIDARG;
01084 
01085             if (len < (int)sizeof(WIN32_FIND_DATAA))
01086                 return E_INVALIDARG;
01087 
01088             ZeroMemory(pfd, sizeof (WIN32_FIND_DATAA));
01089             _ILGetFileDateTime( pidl, &(pfd->ftLastWriteTime));
01090             pfd->dwFileAttributes = _ILGetFileAttributes(pidl, NULL, 0);
01091             pfd->nFileSizeLow = _ILGetFileSize ( pidl, NULL, 0);
01092 
01093             filename = _ILGetTextPointer(pidl);
01094             shortname = _ILGetSTextPointer(pidl);
01095 
01096             if (filename)
01097                 lstrcpynA(pfd->cFileName, filename, sizeof(pfd->cFileName));
01098             else
01099                 pfd->cFileName[0] = '\0';
01100 
01101             if (shortname)
01102                 lstrcpynA(pfd->cAlternateFileName, shortname, sizeof(pfd->cAlternateFileName));
01103             else
01104                 pfd->cAlternateFileName[0] = '\0';
01105             return NOERROR;
01106 
01107         case SHGDFIL_NETRESOURCE:
01108         case SHGDFIL_DESCRIPTIONID:
01109             FIXME_(shell)("SHGDFIL %i stub\n", nFormat);
01110             break;
01111 
01112         default:
01113             ERR_(shell)("Unknown SHGDFIL %i, please report\n", nFormat);
01114     }
01115 
01116     return E_INVALIDARG;
01117 }
01118 
01119 /*************************************************************************
01120  * SHGetDataFromIDListW [SHELL32.248]
01121  *
01122  */
01123 HRESULT WINAPI SHGetDataFromIDListW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl,
01124                                     int nFormat, LPVOID dest, int len)
01125 {
01126     LPSTR filename, shortname;
01127     WIN32_FIND_DATAW * pfd = (WIN32_FIND_DATAW *)dest;
01128 
01129     TRACE_(shell)("sf=%p pidl=%p 0x%04x %p 0x%04x stub\n", psf, pidl, nFormat, dest, len);
01130 
01131     pdump(pidl);
01132 
01133     if (!psf || !dest)
01134         return E_INVALIDARG;
01135 
01136     switch (nFormat)
01137     {
01138         case SHGDFIL_FINDDATA:
01139             pfd = (WIN32_FIND_DATAW *)dest;
01140 
01141             if (_ILIsDrive(pidl))
01142                 return E_INVALIDARG;
01143 
01144             if (len < (int)sizeof(WIN32_FIND_DATAW))
01145                 return E_INVALIDARG;
01146 
01147             ZeroMemory(pfd, sizeof (WIN32_FIND_DATAA));
01148             _ILGetFileDateTime( pidl, &(pfd->ftLastWriteTime));
01149             pfd->dwFileAttributes = _ILGetFileAttributes(pidl, NULL, 0);
01150             pfd->nFileSizeLow = _ILGetFileSize ( pidl, NULL, 0);
01151 
01152             filename = _ILGetTextPointer(pidl);
01153             shortname = _ILGetSTextPointer(pidl);
01154 
01155             if (!filename)
01156                 pfd->cFileName[0] = '\0';
01157             else if (!MultiByteToWideChar(CP_ACP, 0, filename, -1, pfd->cFileName, MAX_PATH))
01158                 pfd->cFileName[MAX_PATH-1] = 0;
01159 
01160             if (!shortname)
01161                 pfd->cAlternateFileName[0] = '\0';
01162             else if (!MultiByteToWideChar(CP_ACP, 0, shortname, -1, pfd->cAlternateFileName, 14))
01163                 pfd->cAlternateFileName[13] = 0;
01164             return NOERROR;
01165 
01166         case SHGDFIL_NETRESOURCE:
01167         case SHGDFIL_DESCRIPTIONID:
01168             FIXME_(shell)("SHGDFIL %i stub\n", nFormat);
01169             break;
01170 
01171         default:
01172             ERR_(shell)("Unknown SHGDFIL %i, please report\n", nFormat);
01173     }
01174 
01175     return E_INVALIDARG;
01176 }
01177 
01178 /*************************************************************************
01179  * SHGetPathFromIDListA        [SHELL32.@][NT 4.0: SHELL32.220]
01180  *
01181  * PARAMETERS
01182  *  pidl,   [IN] pidl
01183  *  pszPath [OUT] path
01184  *
01185  * RETURNS
01186  *  path from a passed PIDL.
01187  *
01188  * NOTES
01189  *    NULL returns FALSE
01190  *    desktop pidl gives path to desktop directory back
01191  *    special pidls returning FALSE
01192  */
01193 BOOL WINAPI SHGetPathFromIDListA(LPCITEMIDLIST pidl, LPSTR pszPath)
01194 {
01195     WCHAR wszPath[MAX_PATH];
01196     BOOL bSuccess;
01197 
01198     bSuccess = SHGetPathFromIDListW(pidl, wszPath);
01199     WideCharToMultiByte(CP_ACP, 0, wszPath, -1, pszPath, MAX_PATH, NULL, NULL);
01200 
01201     return bSuccess;
01202 }
01203 
01204 /*************************************************************************
01205  * SHGetPathFromIDListW             [SHELL32.@]
01206  *
01207  * See SHGetPathFromIDListA.
01208  */
01209 BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
01210 {
01211     HRESULT hr;
01212     LPCITEMIDLIST pidlLast;
01213     CComPtr<IShellFolder>        psfFolder;
01214     DWORD dwAttributes;
01215     STRRET strret;
01216 
01217     TRACE_(shell)("(pidl=%p,%p)\n", pidl, pszPath);
01218     pdump(pidl);
01219 
01220     *pszPath = '\0';
01221     if (!pidl)
01222         return FALSE;
01223 
01224     hr = SHBindToParent(pidl, IID_IShellFolder, (VOID**)&psfFolder, &pidlLast);
01225     if (FAILED(hr))
01226     {
01227         ERR("SHBindToParent failed: %x\n", hr);
01228         return FALSE;
01229     }
01230 
01231     dwAttributes = SFGAO_FILESYSTEM;
01232     hr = psfFolder->GetAttributesOf(1, &pidlLast, &dwAttributes);
01233     if (FAILED(hr) || !(dwAttributes & SFGAO_FILESYSTEM))
01234     {
01235         WARN("Wrong dwAttributes or GetAttributesOf failed: %x\n", hr);
01236         return FALSE;
01237     }
01238 
01239     hr = psfFolder->GetDisplayNameOf(pidlLast, SHGDN_FORPARSING, &strret);
01240     if (FAILED(hr)) return FALSE;
01241 
01242     hr = StrRetToBufW(&strret, pidlLast, pszPath, MAX_PATH);
01243 
01244     TRACE_(shell)("-- %s, 0x%08x\n", debugstr_w(pszPath), hr);
01245     return SUCCEEDED(hr);
01246 }
01247 
01248 /*************************************************************************
01249  *    SHBindToParent        [shell version 5.0]
01250  */
01251 HRESULT WINAPI SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCITEMIDLIST *ppidlLast)
01252 {
01253     CComPtr<IShellFolder>        psfDesktop;
01254     HRESULT         hr = E_FAIL;
01255 
01256     TRACE_(shell)("pidl=%p\n", pidl);
01257     pdump(pidl);
01258 
01259     if (!pidl || !ppv)
01260         return E_INVALIDARG;
01261 
01262     *ppv = NULL;
01263     if (ppidlLast)
01264         *ppidlLast = NULL;
01265 
01266     hr = SHGetDesktopFolder(&psfDesktop);
01267     if (FAILED(hr))
01268         return hr;
01269 
01270     if (_ILIsPidlSimple(pidl))
01271     {
01272         /* we are on desktop level */
01273         hr = psfDesktop->QueryInterface(riid, ppv);
01274     }
01275     else
01276     {
01277         LPITEMIDLIST pidlParent = ILClone(pidl);
01278         ILRemoveLastID(pidlParent);
01279         hr = psfDesktop->BindToObject(pidlParent, NULL, riid, ppv);
01280         SHFree (pidlParent);
01281     }
01282 
01283     if (SUCCEEDED(hr) && ppidlLast)
01284         *ppidlLast = ILFindLastID(pidl);
01285 
01286     TRACE_(shell)("-- psf=%p pidl=%p ret=0x%08x\n", *ppv, (ppidlLast) ? *ppidlLast : NULL, hr);
01287     return hr;
01288 }
01289 
01290 /**************************************************************************
01291  *
01292  *        internal functions
01293  *
01294  *    ### 1. section creating pidls ###
01295  *
01296  *************************************************************************
01297  */
01298 
01299 /* Basic PIDL constructor.  Allocates size + 5 bytes, where:
01300  * - two bytes are SHITEMID.cb
01301  * - one byte is PIDLDATA.type
01302  * - two bytes are the NULL PIDL terminator
01303  * Sets type of the returned PIDL to type.
01304  */
01305 static LPITEMIDLIST _ILAlloc(PIDLTYPE type, unsigned int size)
01306 {
01307     LPITEMIDLIST pidlOut = NULL;
01308 
01309     pidlOut = (LPITEMIDLIST)SHAlloc(size + 5);
01310     if(pidlOut)
01311     {
01312         LPPIDLDATA pData;
01313         LPITEMIDLIST pidlNext;
01314 
01315         ZeroMemory(pidlOut, size + 5);
01316         pidlOut->mkid.cb = size + 3;
01317 
01318         pData = _ILGetDataPointer(pidlOut);
01319         if (pData)
01320             pData->type = type;
01321 
01322         pidlNext = ILGetNext(pidlOut);
01323         if (pidlNext)
01324             pidlNext->mkid.cb = 0x00;
01325         TRACE("-- (pidl=%p, size=%u)\n", pidlOut, size);
01326     }
01327 
01328     return pidlOut;
01329 }
01330 
01331 LPITEMIDLIST _ILCreateDesktop(void)
01332 {
01333     LPITEMIDLIST ret;
01334 
01335     TRACE("()\n");
01336     ret = (LPITEMIDLIST)SHAlloc(2);
01337     if (ret)
01338         ret->mkid.cb = 0;
01339     return ret;
01340 }
01341 
01342 LPITEMIDLIST _ILCreateMyComputer(void)
01343 {
01344     TRACE("()\n");
01345     return _ILCreateGuid(PT_GUID, CLSID_MyComputer);
01346 }
01347 
01348 LPITEMIDLIST _ILCreateMyDocuments(void)
01349 {
01350     TRACE("()\n");
01351     return _ILCreateGuid(PT_GUID, CLSID_MyDocuments);
01352 }
01353 
01354 LPITEMIDLIST _ILCreateIExplore(void)
01355 {
01356     TRACE("()\n");
01357     return _ILCreateGuid(PT_GUID, CLSID_Internet);
01358 }
01359 
01360 LPITEMIDLIST _ILCreateControlPanel(void)
01361 {
01362     LPITEMIDLIST parent = _ILCreateGuid(PT_GUID, CLSID_MyComputer), ret = NULL;
01363 
01364     TRACE("()\n");
01365     if (parent)
01366     {
01367         LPITEMIDLIST cpl = _ILCreateGuid(PT_SHELLEXT, CLSID_ControlPanel);
01368 
01369         if (cpl)
01370         {
01371             ret = ILCombine(parent, cpl);
01372             SHFree(cpl);
01373         }
01374         SHFree(parent);
01375     }
01376     return ret;
01377 }
01378 
01379 LPITEMIDLIST _ILCreatePrinters(void)
01380 {
01381     LPITEMIDLIST parent = _ILCreateGuid(PT_GUID, CLSID_MyComputer), ret = NULL;
01382 
01383     TRACE("()\n");
01384     if (parent)
01385     {
01386         LPITEMIDLIST printers = _ILCreateGuid(PT_YAGUID, CLSID_Printers);
01387 
01388         if (printers)
01389         {
01390             ret = ILCombine(parent, printers);
01391             SHFree(printers);
01392         }
01393         SHFree(parent);
01394     }
01395     return ret;
01396 }
01397 
01398 LPITEMIDLIST _ILCreateNetwork(void)
01399 {
01400     TRACE("()\n");
01401     return _ILCreateGuid(PT_GUID, CLSID_NetworkPlaces);
01402 }
01403 
01404 LPITEMIDLIST _ILCreateBitBucket(void)
01405 {
01406     TRACE("()\n");
01407     return _ILCreateGuid(PT_GUID, CLSID_RecycleBin);
01408 }
01409 
01410 LPITEMIDLIST _ILCreateAdminTools(void)
01411 {
01412     TRACE("()\n");
01413     return _ILCreateGuid(PT_GUID, CLSID_AdminFolderShortcut); //FIXME
01414 }
01415 
01416 LPITEMIDLIST _ILCreateGuid(PIDLTYPE type, REFIID guid)
01417 {
01418     LPITEMIDLIST pidlOut;
01419 
01420     if (type == PT_SHELLEXT || type == PT_GUID || type == PT_YAGUID)
01421     {
01422         pidlOut = _ILAlloc(type, sizeof(GUIDStruct));
01423         if (pidlOut)
01424         {
01425             LPPIDLDATA pData = _ILGetDataPointer(pidlOut);
01426 
01427             pData->u.guid.guid = guid;
01428             TRACE("-- create GUID-pidl %s\n",
01429                   debugstr_guid(&(pData->u.guid.guid)));
01430         }
01431     }
01432     else
01433     {
01434         WARN("%d: invalid type for GUID\n", type);
01435         pidlOut = NULL;
01436     }
01437     return pidlOut;
01438 }
01439 
01440 LPITEMIDLIST _ILCreateGuidFromStrA(LPCSTR szGUID)
01441 {
01442     IID iid;
01443 
01444     if (FAILED(SHCLSIDFromStringA(szGUID, &iid)))
01445     {
01446         ERR("%s is not a GUID\n", szGUID);
01447         return NULL;
01448     }
01449     return _ILCreateGuid(PT_GUID, iid);
01450 }
01451 
01452 LPITEMIDLIST _ILCreateGuidFromStrW(LPCWSTR szGUID)
01453 {
01454     IID iid;
01455 
01456     if (FAILED(CLSIDFromString((LPOLESTR)szGUID, &iid)))
01457     {
01458         ERR("%s is not a GUID\n", debugstr_w(szGUID));
01459         return NULL;
01460     }
01461     return _ILCreateGuid(PT_GUID, iid);
01462 }
01463 
01464 LPITEMIDLIST _ILCreateFromFindDataW( const WIN32_FIND_DATAW *wfd )
01465 {
01466     char buff[MAX_PATH + 14 +1]; /* see WIN32_FIND_DATA */
01467     DWORD len, len1, wlen, alen, cbData;
01468     LPITEMIDLIST pidl;
01469     PIDLTYPE type;
01470 
01471     if (!wfd)
01472         return NULL;
01473 
01474     TRACE("(%s, %s)\n", debugstr_w(wfd->cAlternateFileName), debugstr_w(wfd->cFileName));
01475 
01476     /* prepare buffer with both names */
01477     len = WideCharToMultiByte(CP_ACP, 0, wfd->cFileName, -1, buff, MAX_PATH, NULL, NULL);
01478     len1 = WideCharToMultiByte(CP_ACP, 0, wfd->cAlternateFileName, -1, buff + len, sizeof(buff) - len, NULL, NULL);
01479     alen = len + len1;
01480 
01481     type = (wfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? PT_FOLDER : PT_VALUE;
01482 
01483     wlen = wcslen(wfd->cFileName) + 1;
01484     cbData = sizeof(FileStruct) - 1 + (alen + (alen & 1)); // Note: szNames field is initially 1 byte long
01485     cbData += sizeof(FileStructW) - 1 + wlen * sizeof(WCHAR); // Note: wszName field is initially 1 byte long
01486     cbData += sizeof(WORD); // offset to FileStructW
01487     pidl = _ILAlloc(type, cbData);
01488     if (pidl)
01489     {
01490         LPPIDLDATA pData = _ILGetDataPointer(pidl);
01491         FileStruct *fs = &pData->u.file;
01492         FileStructW *fsw;
01493         WORD *pOffsetW;
01494 
01495         FileTimeToDosDateTime( &wfd->ftLastWriteTime, &fs->uFileDate, &fs->uFileTime);
01496         fs->dwFileSize = wfd->nFileSizeLow;
01497         fs->uFileAttribs = wfd->dwFileAttributes;
01498         memcpy(fs->szNames, buff, alen);
01499 
01500         fsw = (FileStructW*)(pData->u.file.szNames + alen + (alen & 0x1));
01501         fsw->cbLen = sizeof(FileStructW) - 1 + wlen * sizeof(WCHAR) + sizeof(WORD);
01502         FileTimeToDosDateTime( &wfd->ftCreationTime, &fsw->uCreationDate, &fsw->uCreationTime);
01503         FileTimeToDosDateTime( &wfd->ftLastAccessTime, &fsw->uLastAccessDate, &fsw->uLastAccessTime);
01504         memcpy(fsw->wszName, wfd->cFileName, wlen * sizeof(WCHAR));
01505 
01506         pOffsetW = (WORD*)((LPBYTE)pidl + pidl->mkid.cb - sizeof(WORD));
01507         *pOffsetW = (LPBYTE)fsw - (LPBYTE)pidl;
01508         TRACE("-- Set Value: %s\n", debugstr_w(fsw->wszName));
01509     }
01510     return pidl;
01511 
01512 }
01513 
01514 HRESULT _ILCreateFromPathW(LPCWSTR szPath, LPITEMIDLIST* ppidl)
01515 {
01516     HANDLE hFile;
01517     WIN32_FIND_DATAW stffile;
01518 
01519     if (!ppidl)
01520         return E_INVALIDARG;
01521 
01522     hFile = FindFirstFileW(szPath, &stffile);
01523     if (hFile == INVALID_HANDLE_VALUE)
01524         return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
01525 
01526     FindClose(hFile);
01527 
01528     *ppidl = _ILCreateFromFindDataW(&stffile);
01529 
01530     return *ppidl ? S_OK : E_OUTOFMEMORY;
01531 }
01532 
01533 LPITEMIDLIST _ILCreateDrive(LPCWSTR lpszNew)
01534 {
01535     LPITEMIDLIST pidlOut;
01536 
01537     TRACE("(%s)\n", debugstr_w(lpszNew));
01538 
01539     pidlOut = _ILAlloc(PT_DRIVE, sizeof(DriveStruct));
01540     if (pidlOut)
01541     {
01542         LPSTR pszDest;
01543 
01544         pszDest = _ILGetTextPointer(pidlOut);
01545         if (pszDest)
01546         {
01547             strcpy(pszDest, "x:\\");
01548             pszDest[0] = towupper(lpszNew[0]);
01549             TRACE("-- create Drive: %s\n", debugstr_a(pszDest));
01550         }
01551     }
01552     return pidlOut;
01553 }
01554 
01555 /**************************************************************************
01556  *  _ILGetDrive()
01557  *
01558  *  Gets the text for the drive eg. 'c:\'
01559  *
01560  * RETURNS
01561  *  strlen (lpszText)
01562  */
01563 DWORD _ILGetDrive(LPCITEMIDLIST pidl, LPSTR pOut, UINT uSize)
01564 {
01565     TRACE("(%p,%p,%u)\n", pidl, pOut, uSize);
01566 
01567     if(_ILIsMyComputer(pidl))
01568         pidl = ILGetNext(pidl);
01569 
01570     if (pidl && _ILIsDrive(pidl))
01571         return _ILSimpleGetText(pidl, pOut, uSize);
01572 
01573     return 0;
01574 }
01575 
01576 /**************************************************************************
01577  *
01578  *    ### 2. section testing pidls ###
01579  *
01580  **************************************************************************
01581  *  _ILIsUnicode()
01582  *  _ILIsDesktop()
01583  *  _ILIsMyComputer()
01584  *  _ILIsSpecialFolder()
01585  *  _ILIsDrive()
01586  *  _ILIsFolder()
01587  *  _ILIsValue()
01588  *  _ILIsPidlSimple()
01589  */
01590 BOOL _ILIsUnicode(LPCITEMIDLIST pidl)
01591 {
01592     LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
01593 
01594     TRACE("(%p)\n", pidl);
01595 
01596     return (pidl && lpPData && PT_VALUEW == lpPData->type);
01597 }
01598 
01599 BOOL _ILIsDesktop(LPCITEMIDLIST pidl)
01600 {
01601     TRACE("(%p)\n", pidl);
01602 
01603     return pidl && pidl->mkid.cb ? 0 : 1;
01604 }
01605 
01606 BOOL _ILIsMyDocuments(LPCITEMIDLIST pidl)
01607 {
01608     IID *iid = _ILGetGUIDPointer(pidl);
01609 
01610     TRACE("(%p)\n", pidl);
01611 
01612     if (iid)
01613         return IsEqualIID(*iid, CLSID_MyDocuments);
01614     return FALSE;
01615 }
01616 
01617 BOOL _ILIsControlPanel(LPCITEMIDLIST pidl)
01618 {
01619     IID *iid = _ILGetGUIDPointer(pidl);
01620 
01621     TRACE("(%p)\n", pidl);
01622 
01623     if (iid)
01624         return IsEqualIID(*iid, CLSID_ControlPanel);
01625     return FALSE;
01626 }
01627 
01628 BOOL _ILIsNetHood(LPCITEMIDLIST pidl)
01629 {
01630     IID *iid = _ILGetGUIDPointer(pidl);
01631 
01632     TRACE("(%p)\n", pidl);
01633 
01634     if (iid)
01635         return IsEqualIID(*iid, CLSID_NetworkPlaces);
01636     return FALSE;
01637 }
01638 
01639 
01640 LPITEMIDLIST _ILCreateNetHood(void)
01641 {
01642     return _ILCreateGuid(PT_GUID, CLSID_NetworkPlaces);
01643 }
01644 
01645 LPITEMIDLIST _ILCreateFont(void)
01646 {
01647     return _ILCreateGuid(PT_GUID, CLSID_FontsFolderShortcut);
01648 }
01649 
01650 BOOL _ILIsMyComputer(LPCITEMIDLIST pidl)
01651 {
01652     IID *iid = _ILGetGUIDPointer(pidl);
01653 
01654     TRACE("(%p)\n", pidl);
01655 
01656     if (iid)
01657         return IsEqualIID(*iid, CLSID_MyComputer);
01658     return FALSE;
01659 }
01660 
01661 BOOL _ILIsPrinter(LPCITEMIDLIST pidl)
01662 {
01663     IID *iid = _ILGetGUIDPointer(pidl);
01664 
01665     TRACE("(%p)\n", pidl);
01666 
01667     if (iid)
01668         return IsEqualIID(*iid, CLSID_Printers);
01669     return FALSE;
01670 }
01671 
01672 BOOL _ILIsBitBucket(LPCITEMIDLIST pidl)
01673 {
01674     IID *iid = _ILGetGUIDPointer(pidl);
01675 
01676     TRACE("(%p)\n", pidl);
01677 
01678     if (iid)
01679         return IsEqualIID(*iid, CLSID_RecycleBin);
01680     return FALSE;
01681 }
01682 
01683 BOOL _ILIsAdminTools(LPCITEMIDLIST pidl)
01684 {
01685     IID *iid = _ILGetGUIDPointer(pidl);
01686 
01687     TRACE("(%p)\n", pidl);
01688 
01689     if (iid)
01690         return IsEqualIID(*iid, CLSID_AdminFolderShortcut);
01691     else
01692         return FALSE;
01693 }
01694 
01695 BOOL _ILIsSpecialFolder (LPCITEMIDLIST pidl)
01696 {
01697     LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
01698 
01699     TRACE("(%p)\n", pidl);
01700 
01701     return (pidl && ( (lpPData && (PT_GUID == lpPData->type || PT_SHELLEXT == lpPData->type || PT_YAGUID == lpPData->type)) ||
01702                       (pidl && pidl->mkid.cb == 0x00)
01703                     ));
01704 }
01705 
01706 BOOL _ILIsDrive(LPCITEMIDLIST pidl)
01707 {
01708     LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
01709 
01710     TRACE("(%p)\n", pidl);
01711 
01712     return (pidl && lpPData && (PT_DRIVE == lpPData->type ||
01713                                 PT_DRIVE1 == lpPData->type ||
01714                                 PT_DRIVE2 == lpPData->type ||
01715                                 PT_DRIVE3 == lpPData->type));
01716 }
01717 
01718 BOOL _ILIsFolder(LPCITEMIDLIST pidl)
01719 {
01720     LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
01721 
01722     TRACE("(%p)\n", pidl);
01723 
01724     return (pidl && lpPData && (PT_FOLDER == lpPData->type || PT_FOLDER1 == lpPData->type));
01725 }
01726 
01727 BOOL _ILIsValue(LPCITEMIDLIST pidl)
01728 {
01729     LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
01730 
01731     TRACE("(%p)\n", pidl);
01732 
01733     return (pidl && lpPData && PT_VALUE == lpPData->type);
01734 }
01735 
01736 BOOL _ILIsCPanelStruct(LPCITEMIDLIST pidl)
01737 {
01738     LPPIDLDATA lpPData = _ILGetDataPointer(pidl);
01739 
01740     TRACE("(%p)\n", pidl);
01741 
01742     return (pidl && lpPData && (lpPData->type == 0));
01743 }
01744 
01745 /**************************************************************************
01746  *    _ILIsPidlSimple
01747  */
01748 BOOL _ILIsPidlSimple(LPCITEMIDLIST pidl)
01749 {
01750     BOOL ret = TRUE;
01751 
01752     if(! _ILIsDesktop(pidl))    /* pidl=NULL or mkid.cb=0 */
01753     {
01754         WORD len = pidl->mkid.cb;
01755         LPCITEMIDLIST pidlnext = (LPCITEMIDLIST) (((const BYTE*)pidl) + len );
01756 
01757         if (pidlnext->mkid.cb)
01758             ret = FALSE;
01759     }
01760 
01761     TRACE("%s\n", ret ? "Yes" : "No");
01762     return ret;
01763 }
01764 
01765 /**************************************************************************
01766  *
01767  *    ### 3. section getting values from pidls ###
01768  */
01769 
01770 /**************************************************************************
01771 *  _ILSimpleGetText
01772 *
01773 * gets the text for the first item in the pidl (eg. simple pidl)
01774 *
01775 * returns the length of the string
01776 */
01777 DWORD _ILSimpleGetText (LPCITEMIDLIST pidl, LPSTR szOut, UINT uOutSize)
01778 {
01779     DWORD        dwReturn = 0;
01780     LPSTR        szSrc;
01781     LPWSTR       szSrcW;
01782     GUID const * riid;
01783     char szTemp[MAX_PATH];
01784 
01785     TRACE("(%p %p %x)\n", pidl, szOut, uOutSize);
01786 
01787     if (!pidl)
01788         return 0;
01789 
01790     if (szOut)
01791         *szOut = 0;
01792 
01793     if (_ILIsDesktop(pidl))
01794     {
01795         /* desktop */
01796         if (HCR_GetClassNameA(CLSID_ShellDesktop, szTemp, MAX_PATH))
01797         {
01798             if (szOut)
01799                 lstrcpynA(szOut, szTemp, uOutSize);
01800 
01801             dwReturn = strlen (szTemp);
01802         }
01803     }
01804     else if (( szSrc = _ILGetTextPointer(pidl) ))
01805     {
01806         /* filesystem */
01807         if (szOut)
01808             lstrcpynA(szOut, szSrc, uOutSize);
01809 
01810         dwReturn = strlen(szSrc);
01811     }
01812     else if (( szSrcW = _ILGetTextPointerW(pidl) ))
01813     {
01814         /* unicode filesystem */
01815         WideCharToMultiByte(CP_ACP, 0, szSrcW, -1, szTemp, MAX_PATH, NULL, NULL);
01816 
01817         if (szOut)
01818             lstrcpynA(szOut, szTemp, uOutSize);
01819 
01820         dwReturn = strlen (szTemp);
01821     }
01822     else if (( riid = _ILGetGUIDPointer(pidl) ))
01823     {
01824         /* special folder */
01825         if (HCR_GetClassNameA(*riid, szTemp, MAX_PATH) )
01826         {
01827             if (szOut)
01828                 lstrcpynA(szOut, szTemp, uOutSize);
01829 
01830             dwReturn = strlen (szTemp);
01831         }
01832     }
01833     else
01834     {
01835         ERR("-- no text\n");
01836     }
01837 
01838     TRACE("-- (%p=%s 0x%08x)\n", szOut, debugstr_a(szOut), dwReturn);
01839     return dwReturn;
01840 }
01841 
01842 /**************************************************************************
01843 *  _ILSimpleGetTextW
01844 *
01845 * gets the text for the first item in the pidl (eg. simple pidl)
01846 *
01847 * returns the length of the string
01848 */
01849 DWORD _ILSimpleGetTextW (LPCITEMIDLIST pidl, LPWSTR szOut, UINT uOutSize)
01850 {
01851     DWORD   dwReturn;
01852     FileStructW *pFileStructW = _ILGetFileStructW(pidl);
01853 
01854     TRACE("(%p %p %x)\n", pidl, szOut, uOutSize);
01855 
01856     if (pFileStructW) {
01857         lstrcpynW(szOut, pFileStructW->wszName, uOutSize);
01858         dwReturn = wcslen(pFileStructW->wszName);
01859     } else {
01860         GUID const * riid;
01861         WCHAR szTemp[MAX_PATH];
01862         LPSTR szSrc;
01863         LPWSTR szSrcW;
01864         dwReturn = 0;
01865 
01866         if (!pidl)
01867             return 0;
01868 
01869         if (szOut)
01870             *szOut = 0;
01871 
01872         if (_ILIsDesktop(pidl))
01873         {
01874             /* desktop */
01875             if (HCR_GetClassNameW(CLSID_ShellDesktop, szTemp, MAX_PATH))
01876             {
01877                 if (szOut)
01878                     lstrcpynW(szOut, szTemp, uOutSize);
01879 
01880                 dwReturn = wcslen (szTemp);
01881             }
01882         }
01883         else if (( szSrcW = _ILGetTextPointerW(pidl) ))
01884         {
01885             /* unicode filesystem */
01886             if (szOut)
01887                 lstrcpynW(szOut, szSrcW, uOutSize);
01888 
01889             dwReturn = wcslen(szSrcW);
01890         }
01891         else if (( szSrc = _ILGetTextPointer(pidl) ))
01892         {
01893             /* filesystem */
01894             MultiByteToWideChar(CP_ACP, 0, szSrc, -1, szTemp, MAX_PATH);
01895 
01896             if (szOut)
01897                 lstrcpynW(szOut, szTemp, uOutSize);
01898 
01899             dwReturn = wcslen (szTemp);
01900         }
01901         else if (( riid = _ILGetGUIDPointer(pidl) ))
01902         {
01903             /* special folder */
01904             if ( HCR_GetClassNameW(*riid, szTemp, MAX_PATH) )
01905             {
01906                 if (szOut)
01907                     lstrcpynW(szOut, szTemp, uOutSize);
01908 
01909                 dwReturn = wcslen (szTemp);
01910             }
01911         }
01912         else
01913         {
01914             ERR("-- no text\n");
01915         }
01916     }
01917 
01918     TRACE("-- (%p=%s 0x%08x)\n", szOut, debugstr_w(szOut), dwReturn);
01919     return dwReturn;
01920 }
01921 
01922 /**************************************************************************
01923  *
01924  *    ### 4. getting pointers to parts of pidls ###
01925  *
01926  **************************************************************************
01927  *  _ILGetDataPointer()
01928  */
01929 LPPIDLDATA _ILGetDataPointer(LPCITEMIDLIST pidl)
01930 {
01931     if(pidl && pidl->mkid.cb != 0x00)
01932         return (LPPIDLDATA)pidl->mkid.abID;
01933     return NULL;
01934 }
01935 
01936 /**************************************************************************
01937  *  _ILGetTextPointerW()
01938  * gets a pointer to the unicode long filename string stored in the pidl
01939  */
01940 static LPWSTR _ILGetTextPointerW(LPCITEMIDLIST pidl)
01941 {
01942     /* TRACE(pidl,"(pidl%p)\n", pidl);*/
01943 
01944     LPPIDLDATA pdata = _ILGetDataPointer(pidl);
01945 
01946     if (!pdata)
01947         return NULL;
01948 
01949     switch (pdata->type)
01950     {
01951         case PT_GUID:
01952         case PT_SHELLEXT:
01953         case PT_YAGUID:
01954             return NULL;
01955 
01956         case PT_DRIVE:
01957         case PT_DRIVE1:
01958         case PT_DRIVE2:
01959         case PT_DRIVE3:
01960             /*return (LPSTR)&(pdata->u.drive.szDriveName);*/
01961             return NULL;
01962 
01963         case PT_FOLDER:
01964         case PT_FOLDER1:
01965         case PT_VALUE:
01966         case PT_IESPECIAL1:
01967         case PT_IESPECIAL2:
01968             /*return (LPSTR)&(pdata->u.file.szNames);*/
01969             return NULL;
01970 
01971         case PT_WORKGRP:
01972         case PT_COMP:
01973         case PT_NETWORK:
01974         case PT_NETPROVIDER:
01975         case PT_SHARE:
01976             /*return (LPSTR)&(pdata->u.network.szNames);*/
01977             return NULL;
01978 
01979         case PT_VALUEW:
01980             return (LPWSTR)pdata->u.file.szNames;
01981     }
01982     return NULL;
01983 }
01984 
01985 
01986 /**************************************************************************
01987  *  _ILGetTextPointer()
01988  * gets a pointer to the long filename string stored in the pidl
01989  */
01990 LPSTR _ILGetTextPointer(LPCITEMIDLIST pidl)
01991 {
01992     /* TRACE(pidl,"(pidl%p)\n", pidl);*/
01993 
01994     LPPIDLDATA pdata = _ILGetDataPointer(pidl);
01995 
01996     if (!pdata)
01997         return NULL;
01998 
01999     switch (pdata->type)
02000     {
02001         case PT_GUID:
02002         case PT_SHELLEXT:
02003         case PT_YAGUID:
02004             return NULL;
02005 
02006         case PT_DRIVE:
02007         case PT_DRIVE1:
02008         case PT_DRIVE2:
02009         case PT_DRIVE3:
02010             return pdata->u.drive.szDriveName;
02011 
02012         case PT_FOLDER:
02013         case PT_FOLDER1:
02014         case PT_VALUE:
02015         case PT_IESPECIAL1:
02016         case PT_IESPECIAL2:
02017             return pdata->u.file.szNames;
02018 
02019         case PT_WORKGRP:
02020         case PT_COMP:
02021         case PT_NETWORK:
02022         case PT_NETPROVIDER:
02023         case PT_SHARE:
02024             return pdata->u.network.szNames;
02025 
02026         case PT_CPLAPPLET:
02027             return pdata->u.cpanel.szName;
02028     }
02029     return NULL;
02030 }
02031 
02032 /**************************************************************************
02033  *  _ILGetSTextPointer()
02034  * gets a pointer to the short filename string stored in the pidl
02035  */
02036 static LPSTR _ILGetSTextPointer(LPCITEMIDLIST pidl)
02037 {
02038     /* TRACE(pidl,"(pidl%p)\n", pidl); */
02039 
02040     LPPIDLDATA pdata = _ILGetDataPointer(pidl);
02041 
02042     if (!pdata)
02043         return NULL;
02044 
02045     switch (pdata->type)
02046     {
02047         case PT_FOLDER:
02048         case PT_VALUE:
02049         case PT_IESPECIAL1:
02050         case PT_IESPECIAL2:
02051             return pdata->u.file.szNames + strlen (pdata->u.file.szNames) + 1;
02052 
02053         case PT_WORKGRP:
02054             return pdata->u.network.szNames + strlen (pdata->u.network.szNames) + 1;
02055     }
02056     return NULL;
02057 }
02058 
02059 /**************************************************************************
02060  * _ILGetGUIDPointer()
02061  *
02062  * returns reference to guid stored in some pidls
02063  */
02064 IID* _ILGetGUIDPointer(LPCITEMIDLIST pidl)
02065 {
02066     LPPIDLDATA pdata = _ILGetDataPointer(pidl);
02067 
02068     TRACE("%p\n", pidl);
02069 
02070     if (!pdata)
02071         return NULL;
02072 
02073     TRACE("pdata->type 0x%04x\n", pdata->type);
02074     switch (pdata->type)
02075     {
02076         case PT_SHELLEXT:
02077         case PT_GUID:
02078         case PT_YAGUID:
02079             return &(pdata->u.guid.guid);
02080 
02081         default:
02082             TRACE("Unknown pidl type 0x%04x\n", pdata->type);
02083             break;
02084     }
02085     return NULL;
02086 }
02087 
02088 /******************************************************************************
02089  * _ILGetFileStructW [Internal]
02090  *
02091  * Get pointer the a SHITEMID's FileStructW field if present
02092  *
02093  * PARAMS
02094  *  pidl [I] The SHITEMID
02095  *
02096  * RETURNS
02097  *  Success: Pointer to pidl's FileStructW field.
02098  *  Failure: NULL
02099  */
02100 FileStructW* _ILGetFileStructW(LPCITEMIDLIST pidl) {
02101     FileStructW *pFileStructW;
02102     WORD cbOffset;
02103 
02104     if (!(_ILIsValue(pidl) || _ILIsFolder(pidl)))
02105         return NULL;
02106 
02107     cbOffset = *(const WORD *)((const BYTE *)pidl + pidl->mkid.cb - sizeof(WORD));
02108     pFileStructW = (FileStructW*)((LPBYTE)pidl + cbOffset);
02109 
02110     /* Currently I don't see a fool prove way to figure out if a pidl is for sure of WinXP
02111      * style with a FileStructW member. If we switch all our shellfolder-implementations to
02112      * the new format, this won't be a problem. For now, we do as many sanity checks as possible. */
02113     if (cbOffset & 0x1 || /* FileStructW member is word aligned in the pidl */
02114             /* FileStructW is positioned after FileStruct */
02115             cbOffset < sizeof(pidl->mkid.cb) + sizeof(PIDLTYPE) + sizeof(FileStruct) ||
02116             /* There has to be enough space at cbOffset in the pidl to hold FileStructW and cbOffset */
02117             cbOffset > pidl->mkid.cb - sizeof(cbOffset) - sizeof(FileStructW) ||
02118             pidl->mkid.cb != cbOffset + pFileStructW->cbLen)
02119     {
02120         ERR("Invalid pidl format (cbOffset = %d)!\n", cbOffset);
02121         return NULL;
02122     }
02123 
02124     return pFileStructW;
02125 }
02126 
02127 /*************************************************************************
02128  * _ILGetFileDateTime
02129  *
02130  * Given the ItemIdList, get the FileTime
02131  *
02132  * PARAMS
02133  *      pidl        [I] The ItemIDList
02134  *      pFt         [I] the resulted FILETIME of the file
02135  *
02136  * RETURNS
02137  *     True if Successful
02138  *
02139  * NOTES
02140  *
02141  */
02142 BOOL _ILGetFileDateTime(LPCITEMIDLIST pidl, FILETIME *pFt)
02143 {
02144     LPPIDLDATA pdata = _ILGetDataPointer(pidl);
02145 
02146     if (!pdata)
02147         return FALSE;
02148 
02149     switch (pdata->type)
02150     {
02151         case PT_FOLDER:
02152         case PT_VALUE:
02153             DosDateTimeToFileTime(pdata->u.file.uFileDate, pdata->u.file.uFileTime, pFt);
02154             break;
02155         default:
02156             return FALSE;
02157     }
02158     return TRUE;
02159 }
02160 
02161 BOOL _ILGetFileDate (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
02162 {
02163     FILETIME ft, lft;
02164     SYSTEMTIME time;
02165     BOOL ret;
02166 
02167     if (_ILGetFileDateTime( pidl, &ft ))
02168     {
02169         FileTimeToLocalFileTime(&ft, &lft);
02170         FileTimeToSystemTime (&lft, &time);
02171 
02172         ret = GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &time, NULL,  pOut, uOutSize);
02173         if (ret)
02174         {
02175             /* Append space + time without seconds */
02176             pOut[ret-1] = ' ';
02177             GetTimeFormatA(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &time, NULL, &pOut[ret], uOutSize - ret);
02178         }
02179     }
02180     else
02181     {
02182         pOut[0] = '\0';
02183         ret = FALSE;
02184     }
02185     return ret;
02186 }
02187 
02188 /*************************************************************************
02189  * _ILGetFileSize
02190  *
02191  * Given the ItemIdList, get the FileSize
02192  *
02193  * PARAMS
02194  *    pidl     [I] The ItemIDList
02195  *    pOut     [I] The buffer to save the result
02196  *    uOutsize [I] The size of the buffer
02197  *
02198  * RETURNS
02199  *    The FileSize
02200  *
02201  * NOTES
02202  *    pOut can be null when no string is needed
02203  *
02204  */
02205 DWORD _ILGetFileSize (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
02206 {
02207     LPPIDLDATA pdata = _ILGetDataPointer(pidl);
02208     DWORD dwSize;
02209 
02210     if (!pdata)
02211         return 0;
02212 
02213     switch (pdata->type)
02214     {
02215         case PT_VALUE:
02216             dwSize = pdata->u.file.dwFileSize;
02217             if (pOut)
02218                 StrFormatKBSizeA(dwSize, pOut, uOutSize);
02219             return dwSize;
02220     }
02221     if (pOut)
02222         *pOut = 0x00;
02223     return 0;
02224 }
02225 
02226 BOOL _ILGetExtension (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
02227 {
02228     char szTemp[MAX_PATH];
02229     const char * pPoint;
02230     LPCITEMIDLIST  pidlTemp = pidl;
02231 
02232     TRACE("pidl=%p\n", pidl);
02233 
02234     if (!pidl)
02235         return FALSE;
02236 
02237     pidlTemp = ILFindLastID(pidl);
02238 
02239     if (!_ILIsValue(pidlTemp))
02240         return FALSE;
02241     if (!_ILSimpleGetText(pidlTemp, szTemp, MAX_PATH))
02242         return FALSE;
02243 
02244     pPoint = PathFindExtensionA(szTemp);
02245 
02246     if (!*pPoint)
02247         return FALSE;
02248 
02249     pPoint++;
02250     lstrcpynA(pOut, pPoint, uOutSize);
02251     TRACE("%s\n", pOut);
02252 
02253     return TRUE;
02254 }
02255 
02256 /*************************************************************************
02257  * _ILGetFileType
02258  *
02259  * Given the ItemIdList, get the file type description
02260  *
02261  * PARAMS
02262  *      pidl        [I] The ItemIDList (simple)
02263  *      pOut        [I] The buffer to save the result
02264  *      uOutsize    [I] The size of the buffer
02265  *
02266  * RETURNS
02267  *    nothing
02268  *
02269  * NOTES
02270  *    This function copies as much as possible into the buffer.
02271  */
02272 void _ILGetFileType(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
02273 {
02274     char sType[64];
02275 
02276     if(_ILIsValue(pidl))
02277     {
02278         char sTemp[64];
02279 
02280         if(uOutSize > 0)
02281             pOut[0] = 0;
02282         if (_ILGetExtension (pidl, sType, 64))
02283         {
02284             if (HCR_MapTypeToValueA(sType, sTemp, 64, TRUE))
02285             {
02286                 /* retrieve description */
02287                 if(HCR_MapTypeToValueA(sTemp, pOut, uOutSize, FALSE ))
02288                     return;
02289             }
02290             /* display Ext-file as description */
02291             strcpy(pOut, sType);
02292             _strupr(pOut);
02293             /* load localized file string */
02294             sTemp[0] = '\0';
02295             if(LoadStringA(shell32_hInstance, IDS_SHV_COLUMN1, sTemp, 64))
02296             {
02297                 sTemp[63] = '\0';
02298                 strcat(pOut, "-");
02299                 strcat(pOut, sTemp);
02300             }
02301         }
02302     }
02303     else
02304     {
02305         pOut[0] = '\0';
02306         LoadStringA(shell32_hInstance, IDS_DIRECTORY, pOut, uOutSize);
02307         /* make sure its null terminated */
02308         pOut[uOutSize-1] = '\0';
02309     }
02310 }
02311 
02312 /*************************************************************************
02313  * _ILGetFileAttributes
02314  *
02315  * Given the ItemIdList, get the Attrib string format
02316  *
02317  * PARAMS
02318  *      pidl        [I] The ItemIDList
02319  *      pOut        [I] The buffer to save the result
02320  *      uOutsize    [I] The size of the Buffer
02321  *
02322  * RETURNS
02323  *     Attributes
02324  *
02325  * FIXME
02326  *  return value 0 in case of error is a valid return value
02327  *
02328  */
02329 DWORD _ILGetFileAttributes(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
02330 {
02331     LPPIDLDATA pData = _ILGetDataPointer(pidl);
02332     WORD wAttrib = 0;
02333     int i;
02334 
02335     if (!pData)
02336         return 0;
02337 
02338     switch(pData->type)
02339     {
02340         case PT_FOLDER:
02341         case PT_VALUE:
02342             wAttrib = pData->u.file.uFileAttribs;
02343             break;
02344     }
02345 
02346     if(uOutSize >= 6)
02347     {
02348         i = 0;
02349         if(wAttrib & FILE_ATTRIBUTE_READONLY)
02350             pOut[i++] = 'R';
02351         if(wAttrib & FILE_ATTRIBUTE_HIDDEN)
02352             pOut[i++] = 'H';
02353         if(wAttrib & FILE_ATTRIBUTE_SYSTEM)
02354             pOut[i++] = 'S';
02355         if(wAttrib & FILE_ATTRIBUTE_ARCHIVE)
02356             pOut[i++] = 'A';
02357         if(wAttrib & FILE_ATTRIBUTE_COMPRESSED)
02358             pOut[i++] = 'C';
02359         pOut[i] = 0x00;
02360     }
02361     return wAttrib;
02362 }
02363 
02364 /*************************************************************************
02365  * ILFreeaPidl
02366  *
02367  * free a aPidl struct
02368  */
02369 void _ILFreeaPidl(LPITEMIDLIST * apidl, UINT cidl)
02370 {
02371     UINT   i;
02372 
02373     if (apidl)
02374     {
02375         for (i = 0; i < cidl; i++)
02376             SHFree(apidl[i]);
02377         SHFree(apidl);
02378     }
02379 }
02380 
02381 /*************************************************************************
02382  * ILCopyaPidl
02383  *
02384  * copies an aPidl struct
02385  */
02386 LPITEMIDLIST* _ILCopyaPidl(const LPCITEMIDLIST * apidlsrc, UINT cidl)
02387 {
02388     UINT i;
02389     LPITEMIDLIST *apidldest;
02390 
02391     apidldest = (LPITEMIDLIST *)SHAlloc(cidl * sizeof(LPITEMIDLIST));
02392     if (!apidlsrc)
02393         return NULL;
02394 
02395     for (i = 0; i < cidl; i++)
02396         apidldest[i] = ILClone(apidlsrc[i]);
02397 
02398     return apidldest;
02399 }
02400 
02401 /*************************************************************************
02402  * _ILCopyCidaToaPidl
02403  *
02404  * creates aPidl from CIDA
02405  */
02406 LPITEMIDLIST* _ILCopyCidaToaPidl(LPITEMIDLIST* pidl, const CIDA * cida)
02407 {
02408     UINT i;
02409     LPITEMIDLIST *dst;
02410 
02411     dst = (LPITEMIDLIST *)SHAlloc(cida->cidl * sizeof(LPITEMIDLIST));
02412     if (!dst)
02413         return NULL;
02414 
02415     if (pidl)
02416         *pidl = ILClone((LPCITEMIDLIST)(&((const BYTE*)cida)[cida->aoffset[0]]));
02417 
02418     for (i = 0; i < cida->cidl; i++)
02419         dst[i] = ILClone((LPCITEMIDLIST)(&((const BYTE*)cida)[cida->aoffset[i + 1]]));
02420 
02421     return dst;
02422 }

Generated on Sun May 27 2012 04:26:24 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.