// this is workaround function for the Shell API Function SHBindToParent // SHBindToParent is not available under Win95/98 HRESULT CShellContextMenu::SHBindToParentEx (LPCITEMIDLIST pidl, REFIID riid, VOID **ppv, LPCITEMIDLIST *ppidlLast) { HRESULT hr = 0; if (!pidl || !ppv) return E_POINTER; int nCount = GetPIDLCount (pidl); if (nCount == 0) // desktop pidl of invalid pidl return E_POINTER; IShellFolder * psfDesktop = NULL; SHGetDesktopFolder (&psfDesktop); if (nCount == 1) // desktop pidl { if ((hr = psfDesktop->QueryInterface(riid, ppv)) == S_OK) { if (ppidlLast) *ppidlLast = CopyPIDL (pidl); } psfDesktop->Release (); return hr; } LPBYTE pRel = GetPIDLPos (pidl, nCount - 1); LPITEMIDLIST pidlParent = NULL; pidlParent = CopyPIDL (pidl, pRel - (LPBYTE) pidl); IShellFolder * psfFolder = NULL; if ((hr = psfDesktop->BindToObject (pidlParent, NULL, __uuidof (psfFolder), (void **) &psfFolder)) != S_OK) { free (pidlParent); psfDesktop->Release (); return hr; } if ((hr = psfFolder->QueryInterface (riid, ppv)) == S_OK) { if (ppidlLast) *ppidlLast = CopyPIDL ((LPCITEMIDLIST) pRel); } free (pidlParent); psfFolder->Release (); psfDesktop->Release (); return hr; }
/* * Class: sun_awt_shell_Win32ShellFolder2 * Method: doGetColumnValue * Signature: (JJI)Ljava/lang/Object; */ JNIEXPORT jobject JNICALL Java_sun_awt_shell_Win32ShellFolder2_doGetColumnValue (JNIEnv *env, jobject obj, jlong iShellFolder, jlong jpidl, jint columnIdx) { HRESULT hr; IShellFolder *pIShellFolder = (IShellFolder*) iShellFolder; IUnknown *pIUnknown = NULL; LPITEMIDLIST pidl = (LPITEMIDLIST) jpidl; SHELLDETAILS sd; hr = pIShellFolder->QueryInterface(IID_IShellFolder2, (void**)&pIUnknown); if(SUCCEEDED (hr)) { // The folder exposes IShellFolder2 interface IShellFolder2 *pIShellFolder2 = (IShellFolder2*) pIUnknown; hr = pIShellFolder2->GetDetailsOf(pidl, (UINT)columnIdx, &sd); pIShellFolder2->Release(); if (SUCCEEDED (hr)) { STRRET strRet = sd.str; return jstringFromSTRRET(env, pidl, &strRet); } } hr = pIShellFolder->CreateViewObject(NULL, IID_IShellDetails, (void**)&pIUnknown); if(SUCCEEDED (hr)) { // The folder exposes IShellDetails interface IShellDetails *pIShellDetails = (IShellDetails*) pIUnknown; hr = pIShellDetails->GetDetailsOf(pidl, (UINT)columnIdx, &sd); pIShellDetails->Release(); if (SUCCEEDED (hr)) { STRRET strRet = sd.str; return jstringFromSTRRET(env, pidl, &strRet); } } // The folder exposes neither IShellFolder2 nor IShelDetails return NULL; }
/* * Class: sun_awt_shell_Win32ShellFolder2 * Method: doGetColumnInfo * Signature: (J)[Lsun/awt/shell/ShellFolderColumnInfo; */ JNIEXPORT jobjectArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_doGetColumnInfo (JNIEnv *env, jobject obj, jlong iShellFolder) { HRESULT hr; IShellFolder *pIShellFolder = (IShellFolder*) iShellFolder; IUnknown *pIUnknown = NULL; jclass columnClass = env->FindClass("sun/awt/shell/ShellFolderColumnInfo"); if(NULL == columnClass) { return NULL; } jmethodID columnConstructor = env->GetMethodID(columnClass, "<init>", "(Ljava/lang/String;IIZ)V"); if(NULL == columnConstructor) { return NULL; } // We'are asking the object the list of available columns SHELLDETAILS sd; hr = pIShellFolder->QueryInterface(IID_IShellFolder2, (void**)&pIUnknown); if(SUCCEEDED (hr)) { // The folder exposes IShellFolder2 interface IShellFolder2 *pIShellFolder2 = (IShellFolder2*) pIUnknown; // Count columns int colNum = -1; hr = S_OK; do{ hr = pIShellFolder2->GetDetailsOf(NULL, ++colNum, &sd); } while (SUCCEEDED (hr)); jobjectArray columns = env->NewObjectArray((jsize) colNum, columnClass, NULL); if(NULL == columns) { pIShellFolder2->Release(); return NULL; } // Fill column details list SHCOLSTATEF csFlags; colNum = 0; hr = S_OK; while (SUCCEEDED (hr)) { hr = pIShellFolder2->GetDetailsOf(NULL, colNum, &sd); if (SUCCEEDED (hr)) { hr = pIShellFolder2->GetDefaultColumnState(colNum, &csFlags); if (SUCCEEDED (hr)) { if(!(csFlags & SHCOLSTATE_HIDDEN)) { jobject column = CreateColumnInfo(env, &columnClass, &columnConstructor, &sd, csFlags & SHCOLSTATE_ONBYDEFAULT); if(!column){ pIShellFolder2->Release(); return NULL; } env->SetObjectArrayElement(columns, (jsize) colNum, column); } } colNum++; } } pIShellFolder2->Release(); return columns; } hr = pIShellFolder->CreateViewObject(NULL, IID_IShellDetails, (void**)&pIUnknown); if(SUCCEEDED (hr)) { // The folder exposes IShellDetails interface IShellDetails *pIShellDetails = (IShellDetails*) pIUnknown; // Count columns int colNum = -1; hr = S_OK; do{ hr = pIShellDetails->GetDetailsOf(NULL, ++colNum, &sd); } while (SUCCEEDED (hr)); jobjectArray columns = env->NewObjectArray((jsize) colNum, columnClass, NULL); if(NULL == columns) { pIShellDetails->Release(); return NULL; } // Fill column details list colNum = 0; hr = S_OK; while (SUCCEEDED (hr)) { hr = pIShellDetails->GetDetailsOf(NULL, colNum, &sd); if (SUCCEEDED (hr)) { jobject column = CreateColumnInfo(env, &columnClass, &columnConstructor, &sd, 1); if(!column){ pIShellDetails->Release(); return NULL; } env->SetObjectArrayElement(columns, (jsize) colNum++, column); } } pIShellDetails->Release(); return columns; } // The folder exposes neither IShellFolder2 nor IShelDetails return NULL; }
static BOOL GetPidlAndShellFolder (char* pszPath, IShellFolder** ppsfOut, LPITEMIDLIST* ppidlOut) { IShellFolder * pd = NULL; IMalloc* shMalloc = NULL; LPITEMIDLIST pidlFull = NULL; ULONG cch; ULONG attrs; BOOL success = FALSE; if (!SUCCEEDED (SHGetDesktopFolder (&pd))) goto BailOut; if (!SUCCEEDED (SHGetMalloc (&shMalloc))) goto BailOut; WCHAR wpath[MAX_PATH]; mbstowcs (wpath, pszPath, 1+lstrlen(pszPath)); //get fully-qualified pidl if (!SUCCEEDED (pd->ParseDisplayName (NULL, NULL, wpath, &cch, &pidlFull, &attrs))) goto BailOut; IShellFolder *psfCurr, *psfNext; if (!SUCCEEDED (pd->QueryInterface (IID_IShellFolder, (LPVOID*)&psfCurr))) goto BailOut; //for each pidl component, bind to folder LPITEMIDLIST pidlNext, pidlLast; pidlNext = PidlNext (pidlFull); pidlLast = pidlFull; while (pidlNext->mkid.cb != 0) { UINT uSave = pidlNext->mkid.cb; //stop the chain temporarily pidlNext->mkid.cb = 0; //so we can bind to the next folder 1 deeper if (!SUCCEEDED (psfCurr->BindToObject(pidlLast, NULL, IID_IShellFolder, (LPVOID*)&psfNext))) goto BailOut; pidlNext->mkid.cb = uSave; //restore the chain psfCurr->Release(); //and set up to work with the next-level folder psfCurr = psfNext; pidlLast = pidlNext; pidlNext = PidlNext (pidlNext); //advance to next pidl } success = TRUE; *ppidlOut = CopyPidl (pidlLast, shMalloc); *ppsfOut = psfCurr; BailOut: //cleanup if (pidlFull != NULL && shMalloc != NULL) shMalloc->Free (pidlFull); //other pidl's were only offsets into this, and don't need freeing if (pd != NULL) pd->Release(); if (shMalloc != NULL) shMalloc->Release(); return success; }
STDAPI _IEBindToObjectInternal(BOOL fStrictBind, LPCITEMIDLIST pidl, IBindCtx * pbc, REFIID riid, void **ppvOut) { IShellFolder *psfTemp; HRESULT hr; *ppvOut = NULL; BOOL fIsUrlChild = IsURLChild(pidl, TRUE); if (fIsUrlChild || ILIsRooted(pidl)) { hr = _GetRoot(pidl, fIsUrlChild, &psfTemp); if (SUCCEEDED(hr)) { pidl = _ILNext(pidl); if (!ILIsEmpty(pidl)) hr = psfTemp->BindToObject(pidl, pbc, riid, ppvOut); else hr = psfTemp->QueryInterface(riid, ppvOut); psfTemp->Release(); } } else { // non integrated browser mode will succeed on // BindToObject(IID_IShellFolder) even for things that should // fail (files). to avoid the down stream problems caused by this we // filter out things that are not "browseable" up front, // // NOTE: this does not work on simple PIDLs DWORD dwAttribs = SFGAO_FOLDER | SFGAO_BROWSABLE | SFGAO_FILESYSTEM; hr = _IEGetAttributesOf(pidl, &dwAttribs, fStrictBind); if (SUCCEEDED(hr)) { switch (_ShouldDocObjBind(dwAttribs, fStrictBind)) { case SHOULDBIND_DOCOBJ: { // // shortcircuit and bind using our CDocObjectFolder for // files which are BROWSABLE. Without this code, file: // to non-Docobject files (such as multi-media files) // won't do anything. // // is is needed for non integraded browser mode // CDocObjectFolder *pdof = new CDocObjectFolder(); TraceMsg(TF_URLNAMESPACE, "IEBTO(%x) using DocObjectFolder", pidl); if (pdof) { hr = pdof->Initialize(pidl); if (SUCCEEDED(hr)) hr = pdof->QueryInterface(riid, ppvOut); pdof->Release(); } else hr = E_OUTOFMEMORY; } break; case SHOULDBIND_DESKTOP: { // // This is the normal case. We just bind down through the desktop... // TraceMsg(TF_URLNAMESPACE, "IEBTO(%x) using Desktop", pidl); hr = SHGetDesktopFolder(&psfTemp); if (SUCCEEDED(hr)) { // BRYANST: 7/22/97 - NT Bug #188099 // shell32.dll in IE4 SI and only in that version had a bug if pbc was passed // to IShellFolder::BindToObject() (fstreex.c!FSBindToFSFolder), it would fail // to bind to Shell Extensions that extended file system folders, such as: // the history folder, the occache, etc. We work around this by passing a NULL pbc // if the destination is an IE4 shell32.dll and it will go thru FSBindToFSFolder(). if (pbc && ShouldWorkAroundBCBug(pidl)) { pbc = NULL; } hr = psfTemp->BindToObject(pidl, pbc, riid, ppvOut); psfTemp->Release(); } } break; default: hr = E_FAIL; } } } }