Error with NumGet() when converting to v2 Topic is solved

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
one1tick
Posts: 32
Joined: 04 Mar 2022, 04:26

Error with NumGet() when converting to v2

Post by one1tick » 20 Nov 2022, 06:57

Hi, I am trying to convert an old usefull lib to v2 but there is an issue with NumGet() => Error: Invalid parameter(s) on line 74 and probably on the follwing use of NumGet().
I don't understand the issue as I tried several thing to check...
As I am not a pro of NumGet()/NumPut() I would be happy if someone can help me on this issue.
Thanks a lot in advance.

Code: Select all

#Requires AutoHotkey v2.0-beta
ShellFileOperation(0x1, "C:\Text.txt", "D:\", 0x100)
return

/*
    https://github.com/denolfe/AutoHotkey/blob/master/lib/ShellFileOperation.ahk

	Provides access to Windows built-in file operation system
	(move / copy / rename / delete files or folders with the standard Windows dialog and error UI).
	Utilizes the SHFileOperation shell function in Windows.

	Release #3

	Joshua A. Kinnison
	2010-09-29, 15:12
*/

ShellFileOperation(fileO := 0x0, fSource := "", fTarget := "", flags := 0x0, ghwnd := 0x0)
{    ;dout_f(A_THisFunc)

    ; AVAILABLE OPERATIONS
    static FO_MOVE := 0x1
    static FO_COPY := 0x2
    static FO_DELETE := 0x3
    static FO_RENAME := 0x4

    ; AVAILABLE FLAGS
    static FOF_MULTIDESTFILES := 0x1    ; Indicates that the to member specifies multiple destination files (one for each source file) rather than one directory where all source files are to be deposited.
    static FOF_CONFIRMMOUSE := 0x2    ; ?
    static FOF_SILENT := 0x4    ; Does not display a progress dialog box.
    static FOF_RENAMEONCOLLISION := 0x8    ; Gives the file being operated on a new name (such as "Copy #1 of...") in a move, copy, or rename operation if a file of the target name already exists.
    static FOF_NOCONFIRMATION := 0x10    ; Responds with "yes to all" for any dialog box that is displayed.
    static FOF_WANTMAPPINGHANDLE := 0x20    ; returns info about the actual result of the operation
    static FOF_ALLOWUNDO := 0x40    ; Preserves undo information, if possible. With del, uses recycle bin.
    static FOF_FILESONLY := 0x80    ; Performs the operation only on files if a wildcard filename (*.*) is specified.
    static FOF_SIMPLEPROGRESS := 0x100    ; Displays a progress dialog box, but does not show the filenames.
    static FOF_NOCONFIRMMKDIR := 0x200    ; Does not confirm the creation of a new directory if the operation requires one to be created.
    static FOF_NOERRORUI := 0x400    ; don't put up error UI
    static FOF_NOCOPYSECURITYATTRIBS := 0x800    ; dont copy file security attributes
    static FOF_NORECURSION := 0x1000    ; Only operate in the specified directory. Don't operate recursively into subdirectories.
    static FOF_NO_CONNECTED_ELEMENTS := 0x2000    ; Do not move connected files as a group (e.g. html file together with images). Only move the specified files.
    static FOF_WANTNUKEWARNING := 0x4000    ; Send a warning if a file is being destroyed during a delete operation rather than recycled. This flag partially overrides FOF_NOCONFIRMATION.
    static FOF_NORECURSEREPARSE := 0x8000    ; treat reparse points as objects, not containers ?

    ; static items for builds without objects
    static _mappings := "mappings"
    static _error := "error"
    static _aborted := "aborted"
    static _num_mappings := "num_mappings"
    static make_object := "Object"

    fileO := fileO ? fileO : fileO

    If (SubStr(flags, 0) == "|")
        flags := SubStr(flags, 1, -1)

    _flags := 0
    Loop Parse, flags, "|"
        _flags |= A_LoopField
    flags := _flags ? _flags : (flags ? flags : flags)

    If (SubStr(fSource, 0) != "|")
        fSource := fSource . "|"

    If (SubStr(fTarget, 0) != "|")
        fTarget := fTarget . "|"

    char_size := 2    ; A_IsUnicode ? 2 : 1
    char_type := "UShort"    ; A_IsUnicode ? "UShort" : "Char"

    fsPtr := &fSource
    Loop (StrLen(fSource)) {
        ; msgbox(fsource " / " A_Index " / " char_size)
        if NumGet(fSource, (A_Index - 1) * char_size, char_type) == 124
            NumPut(0, fSource, (A_Index - 1) * char_size, char_type)
    }

    ftPtr := &fTarget
    Loop (StrLen(fTarget))
        if NumGet(fTarget, (A_Index - 1) * char_size, char_type) == 124
            NumPut(0, fTarget, (A_Index - 1) * char_size, char_type)

    VarSetStrCapacity(SHFILEOPSTRUCT, 60)    ; Encoding SHFILEOPSTRUCT
    NextOffset := NumPut(ghwnd, &SHFILEOPSTRUCT, char_type)    ; hWnd of calling GUI
    NextOffset := NumPut(fileO, NextOffset + 0, char_type)    ; File operation
    NextOffset := NumPut(fsPtr, NextOffset + 0, char_type)    ; Source file / pattern
    NextOffset := NumPut(ftPtr, NextOffset + 0, char_type)    ; Target file / folder
    NextOffset := NumPut(flags, NextOffset + 0, 0, "Short")    ; options

    code := DllCall("Shell32\SHFileOperationW", char_type, &SHFILEOPSTRUCT)
    aborted := NumGet(NextOffset + 0, char_type)
    H2M_ptr := NumGet(NextOffset + 4, char_type)

    ; if !IsFunc(make_object)
    ;     ret := aborted    ; if build doesn't support object, just return the aborted flag
    ; else
    ; {
    ret := %make_object%()
    ret[_mappings] := %make_object%()
    ret[_error] := ErrorLevel := code
    ret[_aborted] := aborted

    if (FOF_WANTMAPPINGHANDLE & flags)
    {
        ; HANDLETOMAPPINGS
        ret[_num_mappings] := NumGet(H2M_ptr + 0, char_type)
        map_ptr := NumGet(H2M_ptr + 4, char_type)

        Loop (ret[_num_mappings])
        {
            ; _SHNAMEMAPPING
            addr := map_ptr + (A_Index - 1) * 16    ;
            old := StrGet(NumGet(addr + 0, char_type))
            new := StrGet(NumGet(addr + 4, char_type))

            ret[_mappings][old] := new
        }
    }
    ; }

    ; free mappings handle if it was requested
    if (FOF_WANTMAPPINGHANDLE & flags)
        DllCall("Shell32\SHFreeNameMappings", char_type, H2M_ptr)

    Return ret
}

Leafk
Posts: 30
Joined: 11 Nov 2022, 22:09

Re: Error with NumGet() when converting to v2

Post by Leafk » 20 Nov 2022, 09:30

I think NumGet is not the problem. It's NumPut.
NumPut has changed it's parameters order ( I was stuck trying to do the same as you with another old code ).

I would try the following (maybe its wrong)

Code: Select all

Loop (StrLen(fTarget))
	if NumGet(fTarget, (A_Index - 1) * char_size, char_type) == 124
		;NumPut(0, fTarget, (A_Index - 1) * char_size, char_type) ;<< old(v1)  NumPut(Number, VarOrAddress , Offset := 0, Type := "UPtr")
		NumPut(char_type, 0, fTarget, (A_Index - 1) * char_size) ;<< new(v2) NumPut Type, Number, Type2, Number2, ... Target , Offset

one1tick
Posts: 32
Joined: 04 Mar 2022, 04:26

Re: Error with NumGet() when converting to v2

Post by one1tick » 20 Nov 2022, 13:37

Thanks, your are right Numput() was wrong but even after the correction I still have an error on the NumGet() line...
Thanks anyway-
Leafk wrote:
20 Nov 2022, 09:30
I think NumGet is not the problem. It's NumPut.
NumPut has changed it's parameters order ( I was stuck trying to do the same as you with another old code ).

I would try the following (maybe its wrong)

Code: Select all

Loop (StrLen(fTarget))
	if NumGet(fTarget, (A_Index - 1) * char_size, char_type) == 124
		;NumPut(0, fTarget, (A_Index - 1) * char_size, char_type) ;<< old(v1)  NumPut(Number, VarOrAddress , Offset := 0, Type := "UPtr")
		NumPut(char_type, 0, fTarget, (A_Index - 1) * char_size) ;<< new(v2) NumPut Type, Number, Type2, Number2, ... Target , Offset

just me
Posts: 9426
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Error with NumGet() when converting to v2

Post by just me » 25 Nov 2022, 10:59

@TheArkive has written a class for SHFileOperation running with v2. You'll find the script on GitHub

one1tick
Posts: 32
Joined: 04 Mar 2022, 04:26

Re: Error with NumGet() when converting to v2

Post by one1tick » 26 Nov 2022, 01:31

thanks @just me it works!
However I would like to solve my issue, the objective being increasing my knowledge ib ahk2.
Thanks.

just me
Posts: 9426
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Error with NumGet() when converting to v2

Post by just me » 26 Nov 2022, 07:15

Hi @one1tick,

there's already a problem in the v1 script you used, it's not 64-bit compatible. The field lengths and offsets of the SHFILEOPSTRUCT structure are:

Code: Select all

Shellapi.h:                         #if !defined(_WIN64)
                                    #include <pshpack1.h>
                                    #endif

                                    typedef WORD FILEOP_FLAGS;

32-bit            64-bit            typedef struct _SHFILEOPSTRUCTA
Offset   Size     Offset   Size     {
0        4        0        8           HWND            hwnd;
4        4        8        4           UINT            wFunc;
8        4        16       8           PCZZSTR         pFrom;
12       4        24       8           PCZZSTR         pTo;
16       2        32       2           FILEOP_FLAGS    fFlags;
18 *     4        36       4           BOOL            fAnyOperationsAborted;
22 *     4        40       8           LPVOID          hNameMappings;
26 *     4        48       8           PCSTR           lpszProgressTitle; // only used if FOF_SIMPLEPROGRESS
         ___               ___      } SHFILEOPSTRUCTA, *LPSHFILEOPSTRUCTA;
         30 *              56

* : non-default alignment
Additionally you have to consider many syntax changes, e.g.
  • &Var doesn't provide the address of the string buffer any more, it provides a VarRef. If you need to pass the address of a string buffer, you have to use StrPtr(Var)
  • Numget/NumPut's Soure/Target parameters must contain a memory address or an object with a .Ptr property providing the address.
  • ...
At last, v2 supports only Unicode, so you don't need checks like

Code: Select all

	char_size := A_IsUnicode ? 2 : 1
	char_type := A_IsUnicode ? "UShort" : "Char"
Hope i could help you a little.

User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

Re: Error with NumGet() when converting to v2  Topic is solved

Post by TheArkive » 26 Nov 2022, 07:25

:D @just me
I remember quite fondly when you explained that to me way back when.

@one1tick
The offsets just me are referring to are addressed on lines 113 and 126 on my github repo pertaining to this function.

How I implemented these offsets is one of many ways it can be done. But it certainly needs to be done for the sake of compatibility.

one1tick
Posts: 32
Joined: 04 Mar 2022, 04:26

Re: Error with NumGet() when converting to v2

Post by one1tick » 30 Nov 2022, 14:53

Thanks guys but it is too complicated for me... I will give up the conversion of that script.
Best.

Post Reply

Return to “Ask for Help (v2)”