I have been experimenting with the IFileOperation interface commands (link) and have run into a problem with the IFileOperationProgressSink notification system (link). The script below works if the ProgressSink is turned off (pProgressSink := 0). When it's turned on, the script crashes.
I am confused about why the RegisterCallback function doesn't appear to receive any parameters beyond the first one. Also, if you run it you will see that the function gets called in the following sequence:
- AddRef
- AddRef
- Release
- PreMoveItem
Code: Select all
#NoEnv
FileAppend, , foo.txt
FileCreateDir, test
Item := A_ScriptDir "\foo.txt"
Folder := A_ScriptDir "\test"
VarSetCapacity(ProgressSink, 20 * A_PtrSize, 0)
NumPut(&ProgressSink + A_PtrSize, ProgressSink, 0, "Ptr")
Loop, 19
NumPut(RegisterCallback("Func", , , A_Index), ProgressSink, A_Index * A_PtrSize, "Ptr")
pProgressSink := &ProgressSink
; pProgressSink := 0 ; The MoveItem command works if this line in not commented
FileOperation := ComObjCreate("{3ad05575-8857-4850-9277-11b85bdb8e09}" ; CLSID
, "{947aab5f-0a5c-4c13-b4d6-4bf7836fc9f8}") ; IID
vtbl := NumGet(FileOperation + 0, 0, "Ptr")
MoveItem := NumGet(vtbl + 0, 14 * A_PtrSize, "Ptr")
PerformOperations := NumGet(vtbl + 0, 21 * A_PtrSize, "Ptr")
r := DllCall(MoveItem, "Ptr", FileOperation
, "Ptr", (pItem := GetShellItem(Item))
, "Ptr", (pFolder := GetShellItem(Folder))
, "Ptr", 0
, "Ptr", pProgressSink
, "UInt")
MsgBox % r "`n" ErrorLevel "`n" A_LastError
DllCall(PerformOperations, "Ptr", FileOperation, "UInt")
MsgBox % r "`n" ErrorLevel "`n" A_LastError
FileRemoveDir, test, 1
ObjRelease(pItem)
ObjRelease(pFolder)
ObjRelease(FileOperation)
ExitApp
GetShellItem(Item) {
VarSetCapacity(IID, 16, 0)
DllCall("Ole32.dll\IIDFromString", "WStr", "{43826d1e-e718-42ee-bc55-a1e261c37bfe}", "Ptr", &IID, "UInt")
DllCall("Shell32.dll\SHCreateItemFromParsingName", "WStr", Item, "Ptr", 0, "Ptr", &IID, "PtrP", pShellItem, "UInt")
Return pShellItem
}
Func(this, params*) {
static SinkMethods := ["QueryInterface","AddRef","Release","StartOperations","FinishOperations","PreRenameItem","PostRenameItem"
,"PreMoveItem","PostMoveItem","PreCopyItem","PostCopyItem","PreDeleteItem","PostDeleteItem","PreNewItem"
,"PostNewItem","UpdateProgress","ResetTimer","PauseTimer","ResumeTimer"]
static s
s .= SinkMethods[A_EventInfo] "-" params.MaxIndex() "`n"
ToolTip % s
}
/*
From C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\um\ShObjIdl_core.h
HRESULT ( STDMETHODCALLTYPE *PreMoveItem )(
__RPC__in IFileOperationProgressSink * This,
/* [in] */ DWORD dwFlags,
/* [in] */ __RPC__in_opt IShellItem *psiItem,
/* [in] */ __RPC__in_opt IShellItem *psiDestinationFolder,
/* [string][unique][in] */ __RPC__in_opt_string LPCWSTR pszNewName);
*/