Q: Pointer to the IUnknown of the IShellItemArray for the IFileOperation::DeleteItems method I am trying to implement the IFileOperation interface and need help with understanding the punkItems parameter of the IFileOperation::DeleteItems method.
On the documentation page the punkItems parameter is described as a

Pointer to the IUnknown of the IShellItemArray, IDataObject, or
  IEnumShellItems object which represents the group of items to be
  copied.

The following code shows how I am using the SHCreateShellItemArrayFromIDLists() function to generate the IShellItemArray:
Files := [A_ScriptDir "\foo1.txt", A_ScriptDir "\foo2.txt"]
IID := "{947aab5f-0a5c-4c13-b4d6-4bf7836fc9f8}"
CLSID := "{3ad05575-8857-4850-9277-11b85bdb8e09}"
FileOperation := ComObjCreate(CLSID, IID)
VTBL := NumGet(FileOperation + 0, 0, "Ptr")
DeleteItems := NumGet(VTBL + 0, 19 * A_PtrSize, "Ptr") ; IFileOperation::DeleteItems
PerformOperations := NumGet(VTBL + 0, 21 * A_PtrSize, "Ptr") ; IFileOperation::PerformOperations

VarSetCapacity(PCIDLIST, A_PtrSize * Files.Count(), 0)
PIDLISTS := []
for Each, File in Files {
   PIDLISTS[Each] := DllCall("Shell32.dll\ILCreateFromPath", "Str", File, "Ptr")
   NumPut(PIDLISTS[Each], PCIDLIST, A_PtrSize * (Each - 1), "Ptr")
}
DllCall("Shell32.dll\SHCreateShellItemArrayFromIDLists", "UInt", Files.Count(), "Ptr", &PCIDLIST, "PtrP", pItems, "Int")
for Each, PIDLIST in PIDLISTS
   DllCall("Shell32.dll\ILFree", "Ptr", PIDLIST)

MsgBox % DllCall(DeleteItems, "Ptr", FileOperation, "Ptr", pItems, "UInt") "`n" ErrorLevel "`n" A_LastError
DllCall(PerformOperations, "Ptr", FileOperation, "Int")
ObjRelease(pItems)

but it feels like I am missing something, e.g. the IUnknown part of the parameter description. The above code works but A_LastError yields ERROR_NO_TOKEN - An attempt was made to reference a token that does not exist (1008). Can you help me understand how would I might get the "Pointer to the IUnknown of the IShellItemArray"?
Thank you.

A: IFileOperation::DeleteItems supports different types of input. 
Just pass in the instance pointer you have (IShellItemArray, IDataObject, IEnumShellItems or IPersistIDList) and the DeleteItems method will treat the input as a IUnknown and call QueryInterface until it finds a type it understands.
You can imagine that the implementation looks something like this:
HRESULT DeleteItems(IUnknown*p)
{
    if (!p->QueryInterface(IShellItemArray)) ...
    else if (!p->QueryInterface(IDataObject)) ...
    ...
    else if (!p->QueryInterface(IPersistIDList)) ...
    else return E_NOINTERFACE;
}

