# Windows API help with CopyFileExA() and Callback to show Progress

**URL:** <https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388>\
**Category:** questions\
**Created:** [August 31, 2022, 2:42pm UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388 "2022-08-31T14:42:38Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![donridley](https://clarionhub.com/user_avatar/clarionhub.com/donridley/32/1459_2.png) [@donridley](https://clarionhub.com/u/donridley)\
**Post date:** [August 31, 2022, 2:42pm UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388/1 "2022-08-31T14:42:38Z")

</div>

My goal is to copy files and display the progress of the copy action with a progress bar.

Note: The files could be quite large.

I found an API that returns the progress to the address of LpprogressRoutine.

What I don’t know is how to code this within the Clarion context.

I’m open to ideas if there’s an easier way to do this.

> BOOL CopyFileExA(
> 
> [in] LPCSTR lpExistingFileName,  
> [in] LPCSTR lpNewFileName,  
> [in, optional] LPPROGRESS\_ROUTINE lpProgressRoutine,  
> [in, optional] LPVOID lpData,  
> [in, optional] LPBOOL pbCancel,  
> [in] DWORD dwCopyFlags  
> );

Callback Routine

> LPPROGRESS\_ROUTINE LpprogressRoutine;
> 
> DWORD LpprogressRoutine(  
> [in] LARGE\_INTEGER TotalFileSize,  
> [in] LARGE\_INTEGER TotalBytesTransferred,  
> [in] LARGE\_INTEGER StreamSize,  
> [in] LARGE\_INTEGER StreamBytesTransferred,  
> [in] DWORD dwStreamNumber,  
> [in] DWORD dwCallbackReason,  
> [in] HANDLE hSourceFile,  
> [in] HANDLE hDestinationFile,  
> [in, optional] LPVOID lpData  
> )

I have this inside a Class CLW:

```
MAP
    MODULE('WinApi')
        drCopyFileExA(STRING lpExistingFileName,STRING lpNewFileName,ULONG lpProgressRoutine,Long lpData,Byte pbCancel,Long dwCopyFlags),byte,PASCAL,name('CopyFileExA')
        !drLpprogressRoutine(Long TotalFileSize,Long TotalBytesTransferred,Long StreamSize,Long StreamBytesTransferred,ULONG dwStreamNumber,ULONG dwCallbackReason,Long hSourceFile,Long hDestinationFile,Long lpData),ULONG,PASCAL,name('LpprogressRoutine')
    End
END

```

Any words of wisdom would be greatly appreciated!

---

<div class="post-metadata">

**Author:** ![CarlBarnes](https://clarionhub.com/user_avatar/clarionhub.com/carlbarnes/32/1859_2.png) [@CarlBarnes](https://clarionhub.com/u/CarlBarnes)\
**Post date:** [August 31, 2022, 3:50pm UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388/2 "2022-08-31T15:50:32Z")

</div>

I’m running out, suggest look at SHFileOperationA that will show its own Progress Window using FOF\_SIMPLEPROGRESS. I thnik you can pass Wnd Hnd as Zero.

> **[SHFileOperationA function (shellapi.h) - Win32 apps](https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shfileoperationa)**
>
> Copies, moves, renames, or deletes a file system object. This function has been replaced in Windows Vista by IFileOperation.

> **[SHFILEOPSTRUCTA (shellapi.h) - Win32 apps](https://learn.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-shfileopstructa)**
>
> Contains information that the SHFileOperation function uses to perform file operations. (ANSI)

Here are some translations. These are partly automated and not tested. You have to read MSDN for details.

```
SHFileOperation PROCEDURE( | !int SHFileOperationA(
      LONG AddressLPSHFILEOPSTRUCTA | !inout LPSHFILEOPSTRUCTA lpFileOp
    ),SIGNED ,RAW,PASCAL,DLL(1),PROC,name('SHFileOperationA')

```

* * *

```
SHFILEOPSTRUCTAtype GROUP,TYPE !,PRE() !typedef struct _SHFILEOPSTRUCTA {
hwnd SIGNED !HWND hwnd
wFunc UNSIGNED !UINT wFunc
pFrom_PCZZSTR_Addr LONG !PCZZSTR pFrom Address of File Name(s) String(s) Double Null Term
pTo_PCZZSTR_Addr LONG !PCZZSTR pTo Address of File Name(s) String(s) Double Null Term
fFlags LONG !FILEOP_FLAGS fFlags
fAnyOperationsAborted BOOL !BOOL fAnyOperationsAborted
hNameMappings UNSIGNED !LPVOID hNameMappings
lpszProgressTitle UNSIGNED !PCSTR lpszProgressTitle - Address of *CSTRING Optional for FOF_SIMPLEPROGRESS
    END ! } SHFILEOPSTRUCTA, *LPSHFILEOPSTRUCTA;

```

I would declare the pFrom and pTo PCZZSTR as a Clarion STRING. Then terminate the file name with  
`'<0,0>' ` .

* * *

```
! Shell File Operations

FO_MOVE EQUATE(0001h) !FO_MOVE 0x0001
FO_COPY EQUATE(0002h) !FO_COPY 0x0002
FO_DELETE EQUATE(0003h) !FO_DELETE 0x0003
FO_RENAME EQUATE(0004h) !FO_RENAME 0x0004

! SHFILEOPSTRUCT.fFlags and IFileOperation::SetOperationFlags() flag values

FOF_MULTIDESTFILES EQUATE(0001h) !FOF_MULTIDESTFILES 0x0001
FOF_CONFIRMMOUSE EQUATE(0002h) !FOF_CONFIRMMOUSE 0x0002
FOF_SILENT EQUATE(0004h) !FOF_SILENT 0x0004 // don't display progress UI (confirm prompts may be displayed still)
FOF_RENAMEONCOLLISION EQUATE(0008h) !FOF_RENAMEONCOLLISION 0x0008 // automatically rename the source files to avoid the collisions
FOF_NOCONFIRMATION EQUATE(0010h) !FOF_NOCONFIRMATION 0x0010 // don't display confirmation UI, assume "yes" for cases that can be bypassed, "no" for those that can not
FOF_WANTMAPPINGHANDLE EQUATE(0020h) !FOF_WANTMAPPINGHANDLE 0x0020 // Fill in SHFILEOPSTRUCT.hNameMappings
! Must be freed using SHFreeNameMappings
FOF_ALLOWUNDO EQUATE(0040h) !FOF_ALLOWUNDO 0x0040 // enable undo including Recycle behavior for IFileOperation::Delete()
FOF_FILESONLY EQUATE(0080h) !FOF_FILESONLY 0x0080 // only operate on the files (non folders), both files and folders are assumed without this
FOF_SIMPLEPROGRESS EQUATE(0100h) !FOF_SIMPLEPROGRESS 0x0100 // means don't show names of files
FOF_NOCONFIRMMKDIR EQUATE(0200h) !FOF_NOCONFIRMMKDIR 0x0200 // don't dispplay confirmatino UI before making any needed directories, assume "Yes" in these cases
FOF_NOERRORUI EQUATE(0400h) !FOF_NOERRORUI 0x0400 // don't put up error UI, other UI may be displayed, progress, confirmations
FOF_NOCOPYSECURITYATTRIBS EQUATE(0800h) !FOF_NOCOPYSECURITYATTRIBS 0x0800 // dont copy file security attributes (ACLs)
FOF_NORECURSION EQUATE(1000h) !FOF_NORECURSION 0x1000 // don't recurse into directories for operations that would recurse
FOF_NO_CONNECTED_ELEMENTS EQUATE(2000h) !FOF_NO_CONNECTED_ELEMENTS 0x2000 // don't operate on connected elements ("xxx_files" folders that go with .htm files)
FOF_WANTNUKEWARNING EQUATE(4000h) !FOF_WANTNUKEWARNING 0x4000 // during delete operation, warn if object is being permanently destroyed instead of recycling (partially overrides FOF_NOCONFIRMATION)
! #if (NTDDI_VERSION >= NTDDI_WINXP)
FOF_NORECURSEREPARSE EQUATE(8000h) !FOF_NORECURSEREPARSE 0x8000 // deprecated; the operations engine always does the right thing on FolderLink objects (symlinks, reparse points, folder shortcuts)
! #endif // (NTDDI_VERSION >= NTDDI_WINXP)
! #define FOF_NO_UI (FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR) // don't display any UI at all

```

---

<div class="post-metadata">

**Author:** ![Mike\_Duglas](https://clarionhub.com/user_avatar/clarionhub.com/mike_duglas/32/1061_2.png) [@Mike\_Duglas](https://clarionhub.com/u/Mike_Duglas)\
**Post date:** [August 31, 2022, 4:16pm UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388/3 "2022-08-31T16:16:08Z")

</div>

You must implement the callback so don’t declare it inside a MODULE, declare it inside a MAP and implement for your needs.

---

<div class="post-metadata">

**Author:** ![anon23294430](https://clarionhub.com/user_avatar/clarionhub.com/anon23294430/32/3829_2.png) [@anon23294430](https://clarionhub.com/u/anon23294430)\
**Post date:** [August 31, 2022, 4:43pm UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388/4 "2022-08-31T16:43:52Z")

</div>

I’ve only used copyfileA in some template Dll’s to move files around so far, but I can see CopyFileEx has the same two parameters as CopyFileA

```
BOOL CopyFileExA(
  [in] LPCSTR lpExistingFileName,
  [in] LPCSTR lpNewFileName,

```

[CopyFileA function (winbase.h) - Win32 apps | Microsoft Docs](https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-copyfilea)

```
BOOL CopyFileA(
  [in] LPCSTR lpExistingFileName,
  [in] LPCSTR lpNewFileName,

```

some hints  
lp = Long Pointer which is a Long in Clarion.  
another way of expressing a long point is to use the \*before the data type, most will be familiar with \*cstring as a parameter, but you could do \*long, and others.  
It boils down to do you want clarion to do this for you  
Loc:Address1 long  
Loc:Address2 long  
Loc:Bool bool  
Loc:ReturnValueBool bool  
Loc:Cstring1 cstring(1000)  
Loc:Cstring2 cstring(1000)  
Loc:ReturnValueBool = CopyFileA(Loc:Address1,Loc:Address2,Loc:Bool)  
Peek(loc:Address1,Loc:cstring1)  
Peek(loc:Address2,Loc:cstring2)

TLDR \* = Peek(LongPointer,DestinationVariable)

As this is attached to a Cstr  
[[MS-DTYP]: LPCSTR | Microsoft Docs](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/f8d4fe46-6be8-44c9-8823-615a21d17a61)

its a CONST in the clarion parameter and it say in the description its a null terminated string of ansi characters. So as its null terminated you would need to use a Clarion cstring as that is also null terminated.

So you have two ways to do the api prototype in Clarion  
CopyFileA(long,long,bool),Bool,Pascal,Name(‘CopyFileA’)  
or  
CopyFileA(CONST \*cstring, CONST \*cstring,bool),bool,Pascal,Name(‘CopyFileA’)  
In clarion CONST tells clarion the parameter being passed by address can not be changed, its treated as a read only a parameter. However you can leave the CONST out of the prototype so it looks like this  
CopyFileA(\*cstring, \*cstring,bool),bool,Pascal,Name(‘CopyFileA’)

Personally I’d get copyFileA working first and then try the CopyFileExA.

Common windows data types can be found here  
[[MS-DTYP]: Common Data Types | Microsoft Docs](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/efda8314-6e41-4837-8299-38ba0ee04b92)

Common windows base types can be found here  
[[MS-DTYP]: Common Base Types | Microsoft Docs](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/3caa4769-b02f-4cee-a857-8496f4395ec1)  
so it should be possible to work out what data type you need or group structure you need to make if you are getting into 64bit territory.

and for callbacks, this might help you

> [@How can I access the raw stack data? MS callback proc prototype changes when asm starts popping the stack](https://clarionhub.com/t/how-can-i-access-the-raw-stack-data-ms-callback-proc-prototype-changes-when-asm-starts-popping-the-stack/5377/18):
>
> For these apis and their Ex versions [EnumResourceTypesA function (winbase.h) - Win32 apps | Microsoft Docs](https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-enumresourcetypesa)[EnumResourceNamesA - Win32 apps | Microsoft Docs](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-enumresourcenamesa)[EnumResourceLanguagesA function (winbase.h) - Win32 apps | Microsoft Docs](https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-enumresourcelanguagesa) with these callback procedures [ENUMRESTYPEPROCA (libloaderapi.h) - Win32 apps | Microsoft Docs](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nc-libloaderapi-enumrestypeproca)[ENUMRESNAMEPROCA (libloaderapi.h) - Win32 apps | Microsoft Docs](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nc-libloaderapi-enumresnameproca)[EnumResLangProc callback function (Windows) | Microsoft Docs](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms648033(v=vs.85)) there is no combination of pragma stateme…

fwiw.

---

<div class="post-metadata">

**Author:** ![donridley](https://clarionhub.com/user_avatar/clarionhub.com/donridley/32/1459_2.png) [@donridley](https://clarionhub.com/u/donridley)\
**Post date:** [August 31, 2022, 5:13pm UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388/5 "2022-08-31T17:13:23Z")

</div>

Hello Mike,

I’ve actually got the callback working except that it GPF’s if I try to get to parameter values.

Thanks!!!

---

<div class="post-metadata">

**Author:** ![MarkGoldberg](https://clarionhub.com/user_avatar/clarionhub.com/markgoldberg/32/1511_2.png) [@MarkGoldberg](https://clarionhub.com/u/MarkGoldberg)\
**Post date:** [August 31, 2022, 6:19pm UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388/6 "2022-08-31T18:19:18Z")

</div>

As mentioned on Skype  
You need to use the 8 byte LARGE ( or ULARGE) instead of the 4 byte LONG

There’s an include, something like i64.inc that has the LARGE data type (sorry I’m away from my computer ATM so I can’t look it up for you)

---

<div class="post-metadata">

**Author:** ![CarlBarnes](https://clarionhub.com/user_avatar/clarionhub.com/carlbarnes/32/1859_2.png) [@CarlBarnes](https://clarionhub.com/u/CarlBarnes)\
**Post date:** [August 31, 2022, 7:30pm UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388/7 "2022-08-31T19:30:47Z")

</div>

I would urge you to try ShellFileOperation. I posted the prototypes back in my prior post. Its not a simple call but it provides its own window with progress and does all the calculations.

For CopyFileExA() to work your prototypes look mostly all wrong to me, but I could be wrong. It has some complex stuff I’m not sure about. The only way to make it work is to dive in and try so if you want it to work just keep going.

> [@donridley](#):
>
> ```auto
> MODULE('WinApi')
> drCopyFileExA(STRING lpExistingFileName, |
> STRING lpNewFileName, |
> ULONG lpProgressRoutine,Long lpData,Byte pbCancel, |
> Long dwCopyFlags),byte,PASCAL,name('CopyFileExA')
> !drLpprogressRoutine(Long TotalFileSize,Long TotalBytesTransferred,Long StreamSize,Long StreamBytesTransferred,ULONG dwStreamNumber,ULONG dwCallbackReason,Long hSourceFile,Long hDestinationFile,Long lpData),ULONG,PASCAL,name('LpprogressRoutine')
> End
> 
> ```

Here’s how I would write the prototypes (not tested). I’m not sure what that pbCancel is about.

```
CopyFileExA PROCEDURE( | !BOOL WINAPI CopyFileExA(
    *CSTRING lpExistingFileName , | !_In_ LPCSTR lpExistingFileName
    *CSTRING lpNewFileName , | !_In_ LPCSTR lpNewFileName
    LONG lpProgressRoutine=0 , | !_In_opt_ LPPROGRESS_ROUTINE lpProgressRoutine Address(CallBack) 
    UNSIGNED lpData=0 , | !_In_opt_ LPVOID lpData
    <*BOOL pbCancel> , | !_Inout_opt_ LPBOOL pbCancel
    UNSIGNED dwCopyFlags | !_In_ DWORD dwCopyFlags
    ),BOOL ,RAW,PASCAL,DLL(1),PROC,name('CopyFileExA')

```

* * *

```
LARGE_INTEGER_In EQUATE(REAL) !??? Not sure this is right ???

LPPROGRESS_ROUTINE PROCEDURE( | !DWORD WINAPI *LPPROGRESS_ROUTINE(
    LARGE_INTEGER_In R_TotalFileSize , | !_In_ ??? LARGE_INTEGER TotalFileSize
    LARGE_INTEGER_In R_TotalBytesTransferred , | !_In_ ??? LARGE_INTEGER TotalBytesTransferred
    LARGE_INTEGER_In R_StreamSize , | !_In_ ??? LARGE_INTEGER StreamSize
    LARGE_INTEGER_In R_StreamBytesTransferred , | !_In_ ??? LARGE_INTEGER StreamBytesTransferred
    UNSIGNED dwStreamNumber , | !_In_ DWORD dwStreamNumber
    UNSIGNED dwCallbackReason , | !_In_ DWORD dwCallbackReason
    SIGNED hSourceFile , | !_In_ HANDLE hSourceFile
    SIGNED hDestinationFile , | !_In_ HANDLE hDestinationFile
    <UNSIGNED lpData> | !_In_opt_ LPVOID lpData
    ) ,UNSIGNED,PASCAL

TotalFileSize LIKE(INT64),OVER(R_TotalFileSize) !??? Not sure this is right
Ditto for other 3 R_xxx

```

A LARGE\_INTEGER is 64 bits, do you know how those work in Clarion and the i64.INC file?

I would have to look at some of my code for Int64 but IIRC an INT64 passed by value uses the 64-bit Floating Point registers so in Clarion need to prototype as a REAL. But its not a REAL so put an INT64 OVER() it.

---

<div class="post-metadata">

**Author:** ![donridley](https://clarionhub.com/user_avatar/clarionhub.com/donridley/32/1459_2.png) [@donridley](https://clarionhub.com/u/donridley)\
**Post date:** [September 1, 2022, 12:41am UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388/8 "2022-09-01T00:41:47Z")

</div>

So I got it working.

Carl’s theory on using REAL’s is spot on.

```
MAP
    CopyProgressRoutine(REAL TotalFileSize,REAL TotalBytesTransferred,REAL StreamSize,REAL StreamBytesTransferred,ULONG dwStreamNumber,ULONG dwCallbackReason,Long hSourceFile,Long hDestinationFile,Long lpData),ULONG,PASCAL,name('LpprogressRoutine')
    MODULE('kernel32.dll') 
        drCopyFileExA(*CSTRING lpExistingFileName,*CSTRING lpNewFileName,ULONG lpProgressRoutine,Long lpData,BOOL pbCancel,DWORD dwCopyFlags),BOOL,PASCAL,RAW,name('CopyFileExA')
    END
END

```

The Callback:

> CopyProgressRoutine Procedure(REAL TotalFileSize,REAL TotalBytesTransferred,REAL StreamSize,REAL StreamBytesTransferred,ULONG dwStreamNumber,ULONG dwCallbackReason,Long hSourceFile,Long hDestinationFile,Long lpData)
> 
> myBase dwrBase  
> st StringTheory  
> TransferredG Group(drINT64),Over(TotalBytesTransferred).  
> FileSizeG Group(drINT64),Over(TotalFileSize).
> 
> ```
> CODE
> !Get the progress
> myBase.SendDebug(myBase.GetProgress(TransferredG.lo,FileSizeG.lo))
> 
> ```

…and the progress window

 ![ScreenHunter 49](https://clarionhub-uploads.s3.eu-north-1.amazonaws.com/original/2X/5/52f027381918441088a270a2727cb803b21165ba.png)

---

<div class="post-metadata">

**Author:** ![CarlBarnes](https://clarionhub.com/user_avatar/clarionhub.com/carlbarnes/32/1859_2.png) [@CarlBarnes](https://clarionhub.com/u/CarlBarnes)\
**Post date:** [September 1, 2022, 1:17am UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388/9 "2022-09-01T01:17:22Z")

</div>

Dang … I made my own little example to prove the REAL worked.

Note this is only for a LARGE\_INTEGER passed by Value, that I think would be rare,  
and not passed by address P LARGE\_INTEGER e.g. see GetDiskFreeSpaceExA()

 ![image](https://clarionhub-uploads.s3.eu-north-1.amazonaws.com/original/2X/b/b6cad27a1ec1851fde4982a4bcba2ffaceaed803.png)

* * *

```
!CopyFileEx with Callback test by Carl Barnes - Copyright 2022 - Released under the MIT License
  PROGRAM

LARGE_INTEGER_In EQUATE(REAL) !64 bit INT passed by value Prototype as REAL

  MAP
TestCopy PROCEDURE()  

CopyFileEx_PPROGRESS PROCEDURE( | !DWORD WINAPI *LPPROGRESS_ROUTINE(
    LARGE_INTEGER_In R_TotalFileSize , | !_In_ LARGE_INTEGER TotalFileSize
    LARGE_INTEGER_In R_TotalBytesTransferred , | !_In_ LARGE_INTEGER TotalBytesTransferred
    LARGE_INTEGER_In R_StreamSize , | !_In_ LARGE_INTEGER StreamSize
    LARGE_INTEGER_In R_StreamBytesTransferred , | !_In_ LARGE_INTEGER StreamBytesTransferred
    UNSIGNED dwStreamNumber , | !_In_ DWORD dwStreamNumber
    UNSIGNED dwCallbackReason , | !_In_ DWORD dwCallbackReason
    SIGNED hSourceFile , | !_In_ HANDLE hSourceFile
    SIGNED hDestinationFile , | !_In_ HANDLE hDestinationFile
    <UNSIGNED lpData> | !_In_opt_ LPVOID lpData
    ),UNSIGNED,PASCAL
  
      MODULE('api')
        OutputDebugString(*CSTRING cMsg),PASCAL,DLL(1),RAW,NAME('OutputDebugStringA')
        GetLastError(),LONG,PASCAL,DLL(1) 

CopyFileEx PROCEDURE( | !BOOL WINAPI CopyFileExA(
    *CSTRING lpExistingFileName , | !_In_ LPCSTR lpExistingFileName
    *CSTRING lpNewFileName , | !_In_ LPCSTR lpNewFileName
    LONG lpProgressRoutine=0 , | !_In_opt_ LPPROGRESS_ROUTINE lpProgressRoutine Address(CallBack) 
    UNSIGNED lpData=0 , | !_In_opt_ LPVOID lpData
    <*BOOL pbCancel> , | !_Inout_opt_ LPBOOL pbCancel
    UNSIGNED dwCopyFlags | !_In_ DWORD dwCopyFlags
    ),BOOL ,RAW,PASCAL,DLL(1),PROC,name('CopyFileExA') !If the function succeeds, the return value is nonzero.
      END !Module API
      
  END

!https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-copyfileexa
COPY_FILE_FAIL_IF_EXISTS EQUATE(00000001h) !The copy operation fails immediately if the target file already exists.
COPY_FILE_NO_BUFFERING EQUATE(00001000h) !The copy operation is performed using unbuffered I/O, bypassing system I/O cache resources. Recommended for very large file transfers.
PROGRESS_CANCEL EQUATE(1) !Cancel the copy operation and delete the destination file.
PROGRESS_CONTINUE EQUATE(0) !Continue the copy operation.
PROGRESS_QUIET EQUATE(3) !Continue the copy operation, but stop invoking CopyProgressRoutine to report progress.
PROGRESS_STOP EQUATE(2) !Stop the copy operation. It can be restarted at a later time.

  CODE
  TestCopy()
  
TestCopy PROCEDURE() 
ExistingFileName CSTRING('XXX.txt') 
NewFileName CSTRING('XXX_Copy.txt')
ProgressRoutine LONG 
lpData LONG 
boolCancel BOOL 
CopyFlags LONG 
RetCopy BOOL 
    CODE
    IF ~EXISTS(ExistingFileName) THEN COPY('CopyFileExTest.clw',ExistingFileName).
    IF ~EXISTS(ExistingFileName) THEN 
        Message('You need to make a file to test copy named: ' & ExistingFileName, 'CopyFileEx Test File')
        RETURN
    END
    REMOVE(NewFileName)
    lpData=8312022
    ProgressRoutine = ADDRESS( CopyFileEx_PPROGRESS )
    RetCopy = CopyFileEx( |         
            ExistingFileName , | ! *CSTRING lpExistingFileName , | !_In_ LPCSTR lpExistingFileName
            NewFileName , | ! *CSTRING lpNewFileName , | !_In_ LPCSTR lpNewFileName
            ProgressRoutine , | ! LONG lpProgressRoutine=0 , | !_In_opt_ LPPROGRESS_ROUTINE lpProgressRoutine Address(CallBack) 
            lpData , | ! UNSIGNED lpData=0 , | !_In_opt_ LPVOID lpData
            boolCancel , | ! <*BOOL pbCancel> , | !_Inout_opt_ LPBOOL pbCancel
            CopyFlags ) ! UNSIGNED dwCopyFlags | !_In_ DWORD dwCopyFlags

    Message('CopyFileEx return='& RetCopy & CHOOSE(~RetCopy,' FAILED',' Success!') & |
            ' <9>LastError='& GetLastError() &|
           '||Copy From: <9>'& ExistingFileName & |
            '|Copy To: <9>'& NewFileName & |
            '','CopyFileEx Test')
    RETURN

!================= 
! https://docs.microsoft.com/en-us/windows/win32/api/winbase/nc-winbase-lpprogress_routine 

CopyFileEx_PPROGRESS PROCEDURE( | !DWORD WINAPI *LPPROGRESS_ROUTINE(
    LARGE_INTEGER_In R_TotalFileSize , | !_In_ LARGE_INTEGER TotalFileSize
    LARGE_INTEGER_In R_TotalBytesTransferred , | !_In_ LARGE_INTEGER TotalBytesTransferred
    LARGE_INTEGER_In R_StreamSize , | !_In_ LARGE_INTEGER StreamSize
    LARGE_INTEGER_In R_StreamBytesTransferred , | !_In_ LARGE_INTEGER StreamBytesTransferred
    UNSIGNED dwStreamNumber , | !_In_ DWORD dwStreamNumber
    UNSIGNED dwCallbackReason , | !_In_ DWORD dwCallbackReason
    SIGNED hSourceFile , | !_In_ HANDLE hSourceFile
    SIGNED hDestinationFile , | !_In_ HANDLE hDestinationFile
    <UNSIGNED lpData> ) !_In_opt_ LPVOID lpData ) !,UNSIGNED ,RAW,PASCAL

!Note: LARGE_INTEGER_In EQUATE(REAL) !64 bit INT passed by value Prototype as REAL
TotalFileSize LIKE(INT64),OVER(R_TotalFileSize) !Passed REAL but its really 64 bit INT
TotalBytesTransferred LIKE(INT64),OVER(R_TotalBytesTransferred) 
StreamSize LIKE(INT64),OVER(R_StreamSize)   
StreamBytesTransferred LIKE(INT64),OVER(R_StreamBytesTransferred)   
ReturnProgress LONG 
    CODE
    CASE Message('In callback lpData=' & lpData & |
            '||TotalFileSize = ' & TotalFileSize.lo & |
            ' <9>TotalBytesTransferred = '& TotalBytesTransferred.lo & |
            '|StreamSize = ' & StreamSize.lo & |
            ' <9>StreamBytesTransferred = ' & StreamBytesTransferred.lo & |
            '||dwStreamNumber = ' & dwStreamNumber & |
            '|dwCallbackReason = '& dwCallbackReason & |
            '|hSourceFile = '& hSourceFile & |
            ' <9>hDestinationFile = '& hDestinationFile & |
            '','CopyFileEx_PPROGRESS',ICON:Copy,'Continue|Quite|Cancel Copy')
    OF 1 ; ReturnProgress = PROGRESS_CONTINUE          
    OF 2 ; ReturnProgress = PROGRESS_QUIET           
    OF 3 ; ReturnProgress = PROGRESS_CANCEL 
    END 
    RETURN ReturnProgress

```

* * *

[CopyFileExTestProject.zip](https://clarionhub.com/uploads/short-url/5rh1bveE6Gv8jTTp9dYokpe5OSA.zip) (2.5 KB)

---

<div class="post-metadata">

**Author:** ![anon23294430](https://clarionhub.com/user_avatar/clarionhub.com/anon23294430/32/3829_2.png) [@anon23294430](https://clarionhub.com/u/anon23294430)\
**Post date:** [September 1, 2022, 4:58am UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388/10 "2022-09-01T04:58:20Z")

</div>

> [@CarlBarnes](#):
>
> Dang … I made my own little example to prove the REAL worked.

Its the same trick I’m using here. 😉

> [@How can I access the raw stack data? MS callback proc prototype changes when asm starts popping the stack](https://clarionhub.com/t/how-can-i-access-the-raw-stack-data-ms-callback-proc-prototype-changes-when-asm-starts-popping-the-stack/5377/18):
>
> For these apis and their Ex versions [EnumResourceTypesA function (winbase.h) - Win32 apps | Microsoft Docs](https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-enumresourcetypesa)[EnumResourceNamesA - Win32 apps | Microsoft Docs](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-enumresourcenamesa)[EnumResourceLanguagesA function (winbase.h) - Win32 apps | Microsoft Docs](https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-enumresourcelanguagesa) with these callback procedures [ENUMRESTYPEPROCA (libloaderapi.h) - Win32 apps | Microsoft Docs](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nc-libloaderapi-enumrestypeproca)[ENUMRESNAMEPROCA (libloaderapi.h) - Win32 apps | Microsoft Docs](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nc-libloaderapi-enumresnameproca)[EnumResLangProc callback function (Windows) | Microsoft Docs](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms648033(v=vs.85)) there is no combination of pragma stateme…

TLDR, the compiler isnt too fussy about the data types used in api declarations in clarion map modules() and windows isnt either **provided the number of bytes of each parameter matches up in the right order.**

A Real is an 8byte data type, so it gets its bytes and only later in the runtime does the code to process a Real get used.

A Real could be used where ever an 8byte parameter is specified, which would be alot of the 64bit api’s.

I should add, where you need to match the calling convention like whats detailed here [x86 calling conventions - Wikipedia](https://en.wikipedia.org/wiki/X86_calling_conventions#List_of_x86_calling_conventions)  
just reverse the order of the parameters like I did, so these are the same

```
  map
  module('win32')
  Pragma ('call(c_conv=> on)')
  someWinAPIusingC(MatchingByteLengthDataType param1, MatchingByteLengthDataType param2),C
  Pragma ('call(c_conv=> off)')
  end
  end

  map
  module('win32')
  someWinAPIusingC(MatchingByteLengthDataType param2, MatchingByteLengthDataType param1)
  end
  end

```

I think its a few levels of progression up from a vintage tupperware shape sorter ball. 🤓

---

<div class="post-metadata">

**Author:** ![sk2107](https://clarionhub.com/user_avatar/clarionhub.com/sk2107/32/3135_2.png) [@sk2107](https://clarionhub.com/u/sk2107)\
**Post date:** [September 2, 2022, 11:56pm UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388/11 "2022-09-02T23:56:35Z")

</div>

> [@CarlBarnes](#):
>
> [CopyFileExTestProject.zip](https://clarionhub.com/uploads/short-url/5rh1bveE6Gv8jTTp9dYokpe5OSA.zip) (2.5 KB)

Hi ,

may it is a silly question but when I tried to compile the example in Clarion 9 I get these errors:

 ![2022-09-03 02 50 37](https://clarionhub-uploads.s3.eu-north-1.amazonaws.com/original/2X/4/486995e94f45ee70cfbb26f84ddfab158c4f7d3b.jpeg)

Thanks

---

<div class="post-metadata">

**Author:** ![CarlBarnes](https://clarionhub.com/user_avatar/clarionhub.com/carlbarnes/32/1859_2.png) [@CarlBarnes](https://clarionhub.com/u/CarlBarnes)\
**Post date:** [September 3, 2022, 2:19am UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388/12 "2022-09-03T02:19:33Z")

</div>

You’ll have to add these types at the top. I think they were added in C11.

```
INT64 GROUP,TYPE
lo ULONG
hi LONG
         END

UINT64 GROUP,TYPE
lo ULONG
hi ULONG
         END

```

---

<div class="post-metadata">

**Author:** ![sk2107](https://clarionhub.com/user_avatar/clarionhub.com/sk2107/32/3135_2.png) [@sk2107](https://clarionhub.com/u/sk2107)\
**Post date:** [September 3, 2022, 11:59am UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388/13 "2022-09-03T11:59:58Z")

</div>

Sorry .. feeling stupid today 🙄

got this error !

![image](https://clarionhub-uploads.s3.eu-north-1.amazonaws.com/original/2X/2/21042633caa0632adb57bd716778eee587ca8156.png)

---

<div class="post-metadata">

**Author:** ![Mike\_Duglas](https://clarionhub.com/user_avatar/clarionhub.com/mike_duglas/32/1061_2.png) [@Mike\_Duglas](https://clarionhub.com/u/Mike_Duglas)\
**Post date:** [September 3, 2022, 1:18pm UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388/14 "2022-09-03T13:18:38Z")

</div>

In C9 you must link win32ext.lib.

---

<div class="post-metadata">

**Author:** ![CarlBarnes](https://clarionhub.com/user_avatar/clarionhub.com/carlbarnes/32/1859_2.png) [@CarlBarnes](https://clarionhub.com/u/CarlBarnes)\
**Post date:** [September 3, 2022, 1:41pm UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388/15 "2022-09-03T13:41:11Z")

</div>

> [@Mike\_Duglas](#):
>
> link win32ext.lib

Which can do in code with:

`PRAGMA('link(win32ext.lib)')`

I put those PRAGMA up just above the MAP. I like that it moves with the code. Can `OMIT('***', _C110_)` … or `_c100_`

---

<div class="post-metadata">

**Author:** ![sk2107](https://clarionhub.com/user_avatar/clarionhub.com/sk2107/32/3135_2.png) [@sk2107](https://clarionhub.com/u/sk2107)\
**Post date:** [September 3, 2022, 2:55pm UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388/16 "2022-09-03T14:55:37Z")

</div>

Very good. thanks.

one last question, I tried to run it in **clarion 6.3** and I got the same error “ **Unresolved External CopyFileExA in CopyFileExTest.obj** ” and I tried to link win32ext.lib but did not work.

thank you for your support.

Regards

---

<div class="post-metadata">

**Author:** ![MarkGoldberg](https://clarionhub.com/user_avatar/clarionhub.com/markgoldberg/32/1511_2.png) [@MarkGoldberg](https://clarionhub.com/u/MarkGoldberg)\
**Post date:** [September 3, 2022, 3:16pm UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388/17 "2022-09-03T15:16:55Z")

</div>

The API doc shows it’s in shell32  
So, using libmaker, create a .lib for this API

You can try adding the entire dll  
But it’s likely that will lead to duplicates.

So delete everything you don’t need inside of libmaker before you save the .lib

Then link in the lib you created

---

<div class="post-metadata">

**Author:** ![CarlBarnes](https://clarionhub.com/user_avatar/clarionhub.com/carlbarnes/32/1859_2.png) [@CarlBarnes](https://clarionhub.com/u/CarlBarnes)\
**Post date:** [September 3, 2022, 3:31pm UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388/18 "2022-09-03T15:31:16Z")

</div>

> [@MarkGoldberg](#):
>
> So delete everything you don’t need inside of libmaker before you save the .lib

With the shipping LibMaker it is a PITA to have to carefully delete all but 1 function. With the " @ArnorBld + Mark + my " LibMaker you can [Search](https://github.com/CarlTBarnes/LibMakerPlus#search-for-symbols-by-name) and [Tag 1+ Functions](https://github.com/CarlTBarnes/LibMakerPlus#tagging) then write just Tagged in the Lib.

A unique feature … You can [Subtract](https://github.com/CarlTBarnes/LibMakerPlus#subtract-library) the current Clarion Win32.Lib so just have left everything missing and will not have duplicate errors. This allows opening a new release ClaRun.dll then subtract a prior release to see new exports that may reveal new RTL features.

> **[GitHub - CarlTBarnes/LibMakerPlus: LibMaker Plus was made for CIDC 2019. It started...](https://github.com/CarlTBarnes/LibMakerPlus)**
>
> LibMaker Plus was made for CIDC 2019. It started as MG LibMaker and I added many features

---

<div class="post-metadata">

**Author:** ![sk2107](https://clarionhub.com/user_avatar/clarionhub.com/sk2107/32/3135_2.png) [@sk2107](https://clarionhub.com/u/sk2107)\
**Post date:** [September 3, 2022, 4:36pm UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388/19 "2022-09-03T16:36:21Z")

</div>

All set and working fine.

thank you all and best regards

---

<div class="post-metadata">

**Author:** ![sk2107](https://clarionhub.com/user_avatar/clarionhub.com/sk2107/32/3135_2.png) [@sk2107](https://clarionhub.com/u/sk2107)\
**Post date:** [September 3, 2022, 5:05pm UTC](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388/20 "2022-09-03T17:05:38Z")

</div>

the conclusion that after creating the new .lib, I compiled the project in Clarion 6.3 under windows 7 32 bit.

the application works fine under window 10 64 bit but crashes in window 7 32 bit ☹

[Next page](https://clarionhub.com/t/windows-api-help-with-copyfileexa-and-callback-to-show-progress/5388.md?page=2)
