-------------------------------------------------------------------------------
                      [BUG/PRB.] VFP 9.0 FIX - THE COPY FILE MODE FOR THE COPY FILE COMMAND
                                January 2024
                 -------------------------------------------------------------------------------
                                     CCB



1. BUG:

     In Visual FoxPro Advanced 64-bit, when we run the COPY FILE command 6-10 times, sometimes vfp will crash.

     There is a test program:

     *PROC testcopyfilecommand

     =STRTOFILE(REPL("a",10),"test.tmp")

     FOR m.n1=1 TO 10
        ?m.n1
        COPY FILE ("test.tmp") TO ("test2.tmp")
        =INKEY(0.5)
     NEXT

     RETURN

     * END OF PROC TESTCOPYFILECOMMAND.


2. CAUSE:

     For Windows Defender, there are 2 processes on Windows 10 version 1903 or later:
     Antimalware Service Executable (MsMpEng.exe)
     Microsoft Malware Protection Copy Accelerator Utility (MpCopyAccelerator.exe)
     there are some compatible problems for Visual FoxPro Advanced 64-bit
     and Microsoft Malware Protection Copy Accelerator Utility (MpCopyAccelerator.exe).

     It seems MpCopyAccelerator.exe creates a new thread,
     but the ThreadStartAddress is incorrect,
     and then it causes an Access Violation Exception (exception code 0xC0000005)!!!

     For Windows Defender, there is only 1 process on some Windows old versions:
     Antimalware Service Executable (MsMpEng.exe)
     there is no any compatible problems.


3. RESOLUTION:

     We can write some code to fix the BUG.

     vfpa_copyfilea_mode :: ; proc near

             push ebp
             mov ebp,esp
             sub esp,80h
             push ebx
             push esi
             push edi

             cmp dword ptr vfpa_sys9122_data,01h
             je vfpa_copyfilea_mode1_start0
             cmp dword ptr vfpa_sys9122_data,02h
             je vfpa_copyfilea_mode2_start0
             jmp vfpa_copyfilea_mode_end

     vfpa_copyfilea_mode1_start0:
             cmp dword ptr [ebp+10h],00h
             je vfpa_copyfilea_mode1_start1
             push 00h
             push 80h ; FILE_ATTRIBUTE_NORMAL
             push 03h ; OPEN_EXISTING
             push 00h
             push 00h
             push 080000000h ; GENERIC_READ
             push dword ptr [ebp+0Ch]
             call CreateFileAs
             mov dword ptr [ebp-10h][8],eax
             test eax,eax
             jl vfpa_copyfilea_mode1_start1
             push dword ptr [ebp-10h][8]
             call CloseHandle
             jmp vfpa_copyfilea_mode1_end0

     vfpa_copyfilea_mode1_end0:
             xor eax,eax
             jmp vfpa_copyfilea_mode_end

     vfpa_copyfilea_mode1_start1:
             call GetProcessHeap
             mov dword ptr [ebp-30h],eax
             push 8000h
             push 00h
             push dword ptr [ebp-30h]
             call HeapAlloc
             mov dword ptr [ebp-30h][8],eax
             test eax,eax
             je vfpa_copyfilea_mode1_end1
             jmp vfpa_copyfilea_mode1_start2

     vfpa_copyfilea_mode1_end1:
             xor eax,eax
             jmp vfpa_copyfilea_mode_end

     vfpa_copyfilea_mode1_start2:
             mov dword ptr [ebp-70h],080000000h
             mov dword ptr [ebp-80h],00h

     vfpa_copyfilea_mode1_start2_createfile:
             push 00h
             push 80h ; FILE_ATTRIBUTE_NORMAL
             push 03h ; OPEN_EXISTING
             push 00h
             push 00h
             push 080000000h ; GENERIC_READ
             push dword ptr [ebp+08h]
             call CreateFileA
             mov dword ptr [ebp-10h],eax
             cmp eax , 0FFFFFFFFh
             jne vfpa_copyfilea_mode1_end20

             call GetLastError
             mov ecx , eax
             mov eax , 0FFFFFFFFh
             cmp ecx , 05h
             je vfpa_copyfilea_mode1_start2_createfile_attribute
             cmp ecx , 20h
             je vfpa_copyfilea_mode1_start2_createfile_attribute
             cmp ecx , 02h
             je vfpa_copyfilea_mode1_end20
             cmp ecx , 03h
             je vfpa_copyfilea_mode1_end20
             cmp ecx , 0Fh
             je vfpa_copyfilea_mode1_end20
             cmp ecx , 07Bh
             je vfpa_copyfilea_mode1_end20
             jmp vfpa_copyfilea_mode1_start2_createfile_attribute

     vfpa_copyfilea_mode1_start2_createfile_attribute ::
             mov edx ,  dword ptr [ebp+08h]
             push edx
             call GetFileAttributesA
             mov ecx , eax
             mov eax , 0FFFFFFFFh
             cmp ecx , 0FFFFFFFFh
             je vfpa_copyfilea_mode1_start2_createfile_cnt
             test ecx , 10h
             jne vfpa_copyfilea_mode1_end20
             test dword ptr [ebp-70h] , 40000000h
             je vfpa_copyfilea_mode1_start2_createfile_cnt
             test ecx , 01h
             jne vfpa_copyfilea_mode1_end20
             jmp vfpa_copyfilea_mode1_start2_createfile_cnt

     vfpa_copyfilea_mode1_start2_createfile_cnt ::
             mov edx ,  dword ptr [ebp+08h]
             push edx
             call lstrlenA
             mov edx ,  dword ptr [ebp+08h]
             add edx , eax
             dec edx
             mov eax , 0FFFFFFFFh
             cmp byte ptr [edx],"\"
             je vfpa_copyfilea_mode1_end20
             mov ecx,dword ptr vfpa_sys9029_data
             inc dword ptr [ebp-80h]
             cmp dword ptr [ebp-80h],ecx
             ja vfpa_copyfilea_mode1_end20
             push dword ptr vfpa_sys9132_data
             call  Sleep
             jmp vfpa_copyfilea_mode1_start2_createfile

     vfpa_copyfilea_mode1_end20:
             test eax,eax
             jl vfpa_copyfilea_mode1_end2
             jmp vfpa_copyfilea_mode1_start3

     vfpa_copyfilea_mode1_end2:
             push dword ptr [ebp-30h][8]
             push 00h
             push dword ptr [ebp-30h]
             call HeapFree
             xor eax,eax
             jmp vfpa_copyfilea_mode_end

     vfpa_copyfilea_mode1_start3:
             mov dword ptr [ebp-70h][8],0C0000000h
             mov dword ptr [ebp-80h][8],00h

     vfpa_copyfilea_mode1_start3_createfile:
             push 00h
             push 80h ; FILE_ATTRIBUTE_NORMAL
             push 02h ; CREATE_ALWAYS
             push 00h
             push 00h
             push 0C0000000h ; GENERIC_READ or GENERIC_WRITE
             push dword ptr [ebp+0Ch]
             call CreateFileA
             mov dword ptr [ebp-10h][8],eax
             cmp eax , 0FFFFFFFFh
             jne vfpa_copyfilea_mode1_end30

             call GetLastError
             mov ecx , eax
             mov eax , 0FFFFFFFFh
             cmp ecx , 05h
             je vfpa_copyfilea_mode1_start3_createfile_attribute
             cmp ecx , 20h
             je vfpa_copyfilea_mode1_start3_createfile_attribute
             cmp ecx , 02h
             je vfpa_copyfilea_mode1_end30
             cmp ecx , 03h
             je vfpa_copyfilea_mode1_end30
             cmp ecx , 0Fh
             je vfpa_copyfilea_mode1_end30
             cmp ecx , 07Bh
             je vfpa_copyfilea_mode1_end30
             jmp vfpa_copyfilea_mode1_start3_createfile_attribute

     vfpa_copyfilea_mode1_start3_createfile_attribute ::
             mov edx ,  dword ptr [ebp+0Ch]
             push edx
             call GetFileAttributesA
             mov ecx , eax
             mov eax , 0FFFFFFFFh
             cmp ecx , 0FFFFFFFFh
             je vfpa_copyfilea_mode1_start3_createfile_cnt
             test ecx , 10h
             jne vfpa_copyfilea_mode1_end30
             test dword ptr [ebp-70h][8] , 40000000h
             je vfpa_copyfilea_mode1_start3_createfile_cnt
             test ecx , 01h
             jne vfpa_copyfilea_mode1_end30
             jmp vfpa_copyfilea_mode1_start3_createfile_cnt

     vfpa_copyfilea_mode1_start3_createfile_cnt ::
             mov edx ,  dword ptr [ebp+0Ch]
             push edx
             call lstrlenA
             mov edx ,  dword ptr [ebp+0Ch]
             add edx , eax
             dec edx
             mov eax , 0FFFFFFFFh
             cmp byte ptr [edx],"\"
             je vfpa_copyfilea_mode1_end30
             mov ecx,dword ptr vfpa_sys9029_data
             inc dword ptr [ebp-80h][8]
             cmp dword ptr [ebp-80h][8],ecx
             ja vfpa_copyfilea_mode1_end30
             push dword ptr vfpa_sys9132_data
             call  Sleep
             jmp vfpa_copyfilea_mode1_start3_createfile

     vfpa_copyfilea_mode1_end30:
             test eax,eax
             jl vfpa_copyfilea_mode1_end3
             jmp vfpa_copyfilea_mode1_start4

     vfpa_copyfilea_mode1_end3:
             push dword ptr [ebp-30h][8]
             push 00h
             push dword ptr [ebp-30h]
             call HeapFree
             push dword ptr [ebp-10h]
             call CloseHandle
             xor eax,eax
             jmp vfpa_copyfilea_mode_end

     vfpa_copyfilea_mode1_start4:
             mov dword ptr [ebp-20h],00h
             push 00h
             lea eax,dword ptr [ebp-20h]
             push eax
             push 8000h
             mov eax,dword ptr [ebp-30h][8]
             push eax
             push dword ptr [ebp-10h]
             call ReadFile
             test eax,eax
             je vfpa_copyfilea_mode1_end4
             cmp dword ptr [ebp-20h],00h
             je vfpa_copyfilea_mode1_end4

             mov dword ptr [ebp-20h][8],00h
             push 00h
             lea eax,dword ptr [ebp-20h][8]
             push eax
             push dword ptr [ebp-20h]
             mov eax,dword ptr [ebp-30h][8]
             push eax
             push dword ptr [ebp-10h][8]
             call WriteFile
             test eax,eax
             je vfpa_copyfilea_mode1_end4
             cmp dword ptr [ebp-20h][8],00h
             je vfpa_copyfilea_mode1_end4
             jmp vfpa_copyfilea_mode1_start4

     vfpa_copyfilea_mode1_end4:
             push dword ptr [ebp-30h][8]
             push 00h
             push dword ptr [ebp-30h]
             call HeapFree

             lea eax,dword ptr [ebp-60h]
             push eax
             lea eax,dword ptr [ebp-50h]
             push eax
             lea eax,dword ptr [ebp-40h]
             push eax
             push dword ptr [ebp-10h]
             call GetFileTime

             lea eax,dword ptr [ebp-60h]
             push eax
             lea eax,dword ptr [ebp-50h]
             push eax
             lea eax,dword ptr [ebp-40h]
             push eax
             push dword ptr [ebp-10h][8]
             call SetFileTime

             push dword ptr [ebp-10h]
             call CloseHandle
             push dword ptr [ebp-10h][8]
             call CloseHandle
             mov eax,01h
             jmp vfpa_copyfilea_mode_end

     vfpa_copyfilea_mode2_start0:
             cmp dword ptr [ebp+10h],00h
             je vfpa_copyfilea_mode2_start1
             push 00h
             push 80h ; FILE_ATTRIBUTE_NORMAL
             push 03h ; OPEN_EXISTING
             push 00h
             push 00h
             push 080000000h ; GENERIC_READ
             push dword ptr [ebp+0Ch]
             call CreateFileA
             mov dword ptr [ebp-10h][8],eax
             test eax,eax
             jl vfpa_copyfilea_mode2_start1
             push dword ptr [ebp-10h][8]
             call CloseHandle
             jmp vfpa_copyfilea_mode2_end0

     vfpa_copyfilea_mode2_end0:
             xor eax,eax
             jmp vfpa_copyfilea_mode_end

     vfpa_copyfilea_mode2_start1:
             lea eax,vfpa_copyfilea_runcopy_file
             push eax
             lea eax,vfpa_copyfilea_runcopy_commandline
             push eax
             call lstrcpyA

             lea eax,vfpa_copyfilea_runcopy_space
             push eax
             lea eax,vfpa_copyfilea_runcopy_commandline
             push eax
             call lstrcatA

             lea eax,vfpa_copyfilea_runcopy_para0
             push eax
             lea eax,vfpa_copyfilea_runcopy_commandline
             push eax
             call lstrcatA

             lea eax,vfpa_copyfilea_runcopy_space
             push eax
             lea eax,vfpa_copyfilea_runcopy_commandline
             push eax
             call lstrcatA

             lea eax,vfpa_copyfilea_runcopy_quotationmark
             push eax
             lea eax,vfpa_copyfilea_runcopy_commandline
             push eax
             call lstrcatA

             push dword ptr [ebp+08h]
             lea eax,vfpa_copyfilea_runcopy_commandline
             push eax
             call lstrcatA

             lea eax,vfpa_copyfilea_runcopy_quotationmark
             push eax
             lea eax,vfpa_copyfilea_runcopy_commandline
             push eax
             call lstrcatA

             lea eax,vfpa_copyfilea_runcopy_space
             push eax
             lea eax,vfpa_copyfilea_runcopy_commandline
             push eax
             call lstrcatA

             lea eax,vfpa_copyfilea_runcopy_quotationmark
             push eax
             lea eax,vfpa_copyfilea_runcopy_commandline
             push eax
             call lstrcatA

             push dword ptr [ebp+0Ch]
             lea eax,vfpa_copyfilea_runcopy_commandline
             push eax
             call lstrcatA

             lea eax,vfpa_copyfilea_runcopy_quotationmark
             push eax
             lea eax,vfpa_copyfilea_runcopy_commandline
             push eax
             call lstrcatA

     vfpa_copyfilea_mode2_start2:
             push dword ptr vfpa_sys9074_data
             call Sleep

             xor eax , eax
             mov dword ptr vfpa_copyfilea_runcopy_startinfo[00h],44h
             mov dword ptr vfpa_copyfilea_runcopy_startinfo[04h],eax
             mov dword ptr vfpa_copyfilea_runcopy_startinfo[08h],eax
             mov dword ptr vfpa_copyfilea_runcopy_startinfo[0Ch],eax
             mov dword ptr vfpa_copyfilea_runcopy_startinfo[10h],eax
             mov dword ptr vfpa_copyfilea_runcopy_startinfo[14h],eax
             mov dword ptr vfpa_copyfilea_runcopy_startinfo[18h],eax
             mov dword ptr vfpa_copyfilea_runcopy_startinfo[1Ch],eax
             mov dword ptr vfpa_copyfilea_runcopy_startinfo[20h],eax
             mov dword ptr vfpa_copyfilea_runcopy_startinfo[24h],eax
             mov dword ptr vfpa_copyfilea_runcopy_startinfo[28h],eax
             mov dword ptr vfpa_copyfilea_runcopy_startinfo[2Ch],81h ; STARTF_USESHOWWINDOW or STARTF_FORCEOFFFEEDBACK
             mov dword ptr vfpa_copyfilea_runcopy_startinfo[30h],eax ; SW_HIDE
             mov dword ptr vfpa_copyfilea_runcopy_startinfo[34h],eax
             mov dword ptr vfpa_copyfilea_runcopy_startinfo[38h],eax
             mov dword ptr vfpa_copyfilea_runcopy_startinfo[3Ch],eax
             mov dword ptr vfpa_copyfilea_runcopy_startinfo[40h],eax

             mov dword ptr vfpa_copyfilea_runcopy_procinfo[00h],eax
             mov dword ptr vfpa_copyfilea_runcopy_procinfo[04h],eax
             mov dword ptr vfpa_copyfilea_runcopy_procinfo[08h],eax
             mov dword ptr vfpa_copyfilea_runcopy_procinfo[0Ch],eax

             lea eax,byte ptr vfpa_copyfilea_runcopy_procinfo
             push eax
             lea eax,byte ptr vfpa_copyfilea_runcopy_startinfo
             push eax
             push 00h
             push 00h
             push 00h
             push 00h
             push 00h
             push 00h
             lea eax,byte ptr vfpa_copyfilea_runcopy_commandline
             push eax
             push 00h
             call CreateProcessA
             test eax,eax
             je vfpa_copyfilea_mode2_end2
             cmp dword ptr vfpa_copyfilea_runcopy_procinfo[00h],00h
             je vfpa_copyfilea_mode2_end2
             jmp vfpa_copyfilea_mode2_start3

     vfpa_copyfilea_mode2_end2:
             xor eax,eax
             jmp vfpa_copyfilea_mode_end

     vfpa_copyfilea_mode2_start3:
             push 07FFFFFFFh
             push dword ptr vfpa_copyfilea_runcopy_procinfo[00h]
             call WaitForSingleObject
             test eax,eax
             jne vfpa_copyfilea_mode2_end3
             jmp vfpa_copyfilea_mode2_start4

     vfpa_copyfilea_mode2_end3:
             xor eax,eax
             jmp vfpa_copyfilea_mode_end

     vfpa_copyfilea_mode2_start4:
             push dword ptr vfpa_sys9074_data
             call Sleep

             push 00h
             push 80h ; FILE_ATTRIBUTE_NORMAL
             push 03h ; OPEN_EXISTING
             push 00h
             push 00h
             push 080000000h ; GENERIC_READ
             push dword ptr [ebp+0Ch]
             call CreateFileA
             mov dword ptr [ebp-10h][8],eax
             test eax,eax
             jl vfpa_copyfilea_mode2_end4
             push dword ptr [ebp-10h][8]
             call CloseHandle
             mov eax,01h
             jmp vfpa_copyfilea_mode_end

     vfpa_copyfilea_mode2_end4:
             xor eax,eax
             jmp vfpa_copyfilea_mode_end

     vfpa_copyfilea_mode_end:
             pop edi
             pop esi
             pop ebx
             mov esp,ebp
             pop ebp
             ret 0Ch

     ; vfpa_copyfilea_mode endp


4. APPLIES TO:

     VFP 10 (VFP Advanced)

     IMPORTANT NOTE FOR WINDOWS 10:
     There are some compatible problems for Visual FoxPro Advanced 64-bit and Windows Defender on Windows 10 version 1903 or later,
     so recommend to set SYS(9122,1) (the default setting) or SYS(9122,2) in Visual FoxPro Advanced 64-bit.


5. REFERENCE WEBSITES:

     1, baiyujia.com:
     http://www.baiyujia.com
     http://www.baiyujia.com/vfpdocuments/f_vfp9fix249.asp
     http://www.baiyujia.com/vfpdocuments/f_vfp9fix35.asp
     http://www.baiyujia.com/vfpdocuments/f_vfp9fix346.asp
     http://www.baiyujia.com/vfpdocuments/f_vfp9fix347.asp

     2, wublub.cn:
     http://www.wublub.cn/index.php/archives/705/

     3, microsoft.com:
     https://learn.microsoft.com/en-us/answers/questions/747179/windows-defender-copy-protection-interferes-with-o


6. OTHER:

     For reference only, there is no guarantees.

     Any questions or suggestions, please send me an email at ccb2000@163.com.