Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpidl.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
1.7.6.1
|