/* * The contents of this file is dual-licensed under 2 * alternative Open Source/Free licenses: LGPL 2.1 or later and * Apache License 2.0. (starting with JNA version 4.0.0). * * You can freely decide which license you want to apply to * the project. * * You may obtain a copy of the LGPL License at: * * http://www.gnu.org/licenses/licenses.html * * A copy is also included in the downloadable source code package * containing JNA, in file "LGPL2.1". * * You may obtain a copy of the Apache License at: * * http://www.apache.org/licenses/ * * A copy is also included in the downloadable source code package * containing JNA, in file "AL2.0". */ package com.sun.jna.platform.win32.COM; /* * @author L W Ahonen, lwahonen@iki.fi */ import com.sun.jna.Function; import com.sun.jna.Pointer; import com.sun.jna.platform.win32.Guid.IID; import com.sun.jna.platform.win32.Guid.REFIID; import com.sun.jna.platform.win32.WinNT; import com.sun.jna.platform.win32.WinNT.HRESULT; import com.sun.jna.ptr.IntByReference; import com.sun.jna.ptr.PointerByReference; public interface IEnumIDList { /** * The interface IID for QueryInterface et al */ public final static IID IID_IEnumIDList = new IID( "{000214F2-0000-0000-C000-000000000046}"); /** * * Retrieves pointers to the supported interfaces on an object. * This method calls IUnknown::AddRef on the pointer it returns. * * @param riid * The identifier of the interface being requested. * * @param ppvObject * The address of a pointer variable that receives the interface pointer requested in the riid parameter. Upon successful * return, *ppvObject contains the requested interface pointer to the object. If the object does not support the * interface, *ppvObject is set to NULL. * * @return * This method returns S_OK if the interface is supported, and E_NOINTERFACE otherwise. If ppvObject is NULL, this method returns E_POINTER. * For any one object, a specific query for the IUnknown interface on any of the object's interfaces must always return the same pointer value. * This enables a client to determine whether two pointers point to the same component by calling QueryInterfacewith IID_IUnknown * and comparing the results. It is specifically not the case that queries for interfaces other than IUnknown (even the same interface * through the same pointer) must return the same pointer value. * * There are four requirements for implementations of QueryInterface (In these cases, "must succeed" means "must succeed barring * catastrophic failure."): * The set of interfaces accessible on an object through QueryInterface must be static, not dynamic. This means that if a call * toQueryInterface for a pointer to a specified interface succeeds the first time, it must succeed again, and if it fails * the first time, it must fail on all subsequent queries.
 * * It must be reflexive: if a client holds a pointer to an interface on an object, and queries for that interface, the call must succeed.
 * * It must be symmetric: if a client holding a pointer to one interface queries successfully for another, a query through * the obtained pointer for the first interface must succeed.
 * * It must be transitive: if a client holding a pointer to one interface queries successfully for a second, and through that * pointer queries successfully for a third interface, a query for the first interface through the pointer for the * third interface must succeed.
 * Notes to Implementers * Implementations of QueryInterface must never check ACLs. The main reason for this rule is that COM requires that an object supporting a * particular interface always return success when queried for that interface. Another reason is that checking ACLs on QueryInterface * does not provide any real security because any client who has access to a particular interface can hand it directly to another * client without any calls back to the server. Also, because COM caches interface pointers, it does not callQueryInterface on * the server every time a client does a query. */ HRESULT QueryInterface( REFIID riid, PointerByReference ppvObject); /** * * Increments the reference count for an interface on an object. This method should be called for every new copy of a pointer to an interface on an object. * @return * The method returns the new reference count. This value is intended to be used only for test purposes. * * Objects use a reference counting mechanism to ensure that the lifetime of the object includes the lifetime of references to it. You use AddRef * to stabilize a copy of an interface pointer. It can also be called when the life of a cloned pointer must extend beyond the * lifetime of the original pointer. The cloned pointer must be released by calling IUnknown::Release. * * The internal reference counter that AddRef maintains should be a 32-bit unsigned integer. * Notes to Callers * Call this method for every new copy of an interface pointer that you make. For example, if you are passing a copy of a pointer * back from a method, you must call AddRef on that pointer. You must also call AddRef on a pointer before passing it as an in-out * parameter to a method; the method will call IUnknown::Release before copying the out-value on top of it. */ int AddRef(); /** * Decrements the reference count for an interface on an object. * * @return * The method returns the new reference count. This value is intended to be used only for test purposes. * * When the reference count on an object reaches zero, Release must cause the interface pointer to free itself. When the released * pointer is the only existing reference to an object (whether the object supports single or multiple interfaces), the * implementation must free the object. * * Note that aggregation of objects restricts the ability to recover interface pointers. * Notes to Callers * Call this method when you no longer need to use an interface pointer. If you are writing a method that takes an in-out * parameter, call Release on the pointer you are passing in before copying the out-value on top of it. */ int Release(); /* Retrieves the specified number of item identifiers in the enumeration sequence and advances the current position by the number of items retrieved. * @param celt * The number of elements in the array referenced by the rgelt parameter. * @param rgelt * The address of a pointer to an array of ITEMIDLIST pointers that receive the item identifiers. * The implementation must allocate these item identifiers using CoTaskMemAlloc. * The calling application is responsible for freeing the item identifiers using CoTaskMemFree. * The ITEMIDLIST structures returned in the array are relative to the IShellFolder being enumerated. * @param pceltFetched * A pointer to a value that receives a count of the item identifiers actually returned in rgelt. * The count can be smaller than the value specified in the celt parameter. This parameter can be NULL on entry only if celt = 1, * because in that case the method can only retrieve one (S_OK) or zero (S_FALSE) items. * * @return HRESULT * Returns S_OK if the method successfully retrieved the requested celt elements. * This method only returns S_OK if the full count of requested items are successfully retrieved. * S_FALSE indicates that more items were requested than remained in the enumeration. * The value pointed to by the pceltFetched parameter specifies the actual number of items retrieved. * Note that the value will be 0 if there are no more items to retrieve. * Returns a COM-defined error value otherwise. * * If this method returns a Component Object Model (COM) error code (as determined by the COMUtils.FAILED macro), * then no entries in the rgelt array are valid on exit. If this method returns a success code (such as S_OK or S_FALSE), * then the ULONG pointed to by the pceltFetched parameter determines how many entries in the rgelt array are valid on exit. * * The distinction is important in the case where celt > 1. For example, if you pass celt=10 and there are only 3 elements left, * *pceltFetched will be 3 and the method will return S_FALSE meaning that you reached the end of the file. * The three fetched elements will be stored into rgelt and are valid. */ HRESULT Next( int celt, PointerByReference rgelt, IntByReference pceltFetched); /** * Skips the specified number of elements in the enumeration sequence. * @param celt * The number of item identifiers to skip. * @return HRESULT * Returns S_OK if successful, or a COM-defined error value otherwise. */ HRESULT Skip( int celt); /** * Returns to the beginning of the enumeration sequence. * @return HRESULT * Returns S_OK if successful, or a COM-defined error value otherwise. */ HRESULT Reset(); /** * Creates a new item enumeration object with the same contents and state as the current one. * @param ppenum * The address of a pointer to the new enumeration object. The calling application must eventually free the new object by calling its Release member function. * @return HRESULT * Returns S_OK if successful, or a COM-defined error value otherwise. */ HRESULT Clone( PointerByReference ppenum); /* Use this like: PointerByReference pbr=new PointerByReference(); HRESULT result=SomeCOMObject.QueryInterface(IID_IEnumIDList, pbr); if(COMUtils.SUCCEEDED(result)) IENumIDList eil=IEnumIDList.Converter.PointerToIEnumIDList(pbr); */ public static class Converter { public static IEnumIDList PointerToIEnumIDList(final PointerByReference ptr) { final Pointer interfacePointer = ptr.getValue(); final Pointer vTablePointer = interfacePointer.getPointer(0); final Pointer[] vTable = new Pointer[7]; vTablePointer.read(0, vTable, 0, 7); return new IEnumIDList() { @Override public WinNT.HRESULT QueryInterface(REFIID byValue, PointerByReference pointerByReference) { Function f = Function.getFunction(vTable[0], Function.ALT_CONVENTION); return new WinNT.HRESULT(f.invokeInt(new Object[]{interfacePointer, byValue, pointerByReference})); } @Override public int AddRef() { Function f = Function.getFunction(vTable[1], Function.ALT_CONVENTION); return f.invokeInt(new Object[]{interfacePointer}); } public int Release() { Function f = Function.getFunction(vTable[2], Function.ALT_CONVENTION); return f.invokeInt(new Object[]{interfacePointer}); } @Override public HRESULT Next(int celt, PointerByReference rgelt, IntByReference pceltFetched) { Function f = Function.getFunction(vTable[3], Function.ALT_CONVENTION); return new HRESULT(f.invokeInt(new Object[]{interfacePointer, celt, rgelt, pceltFetched})); } @Override public HRESULT Skip(int celt) { Function f = Function.getFunction(vTable[4], Function.ALT_CONVENTION); return new HRESULT(f.invokeInt(new Object[]{interfacePointer, celt})); } @Override public HRESULT Reset() { Function f = Function.getFunction(vTable[5], Function.ALT_CONVENTION); return new HRESULT(f.invokeInt(new Object[]{interfacePointer})); } @Override public HRESULT Clone(PointerByReference ppenum) { Function f = Function.getFunction(vTable[6], Function.ALT_CONVENTION); return new HRESULT(f.invokeInt(new Object[]{interfacePointer, ppenum})); } }; } } }