Page 1 of 1

c vs asm - MoveFileEx()/GetLastError()

Posted: Thu Apr 18, 2024 12:56 pm
by jassing
when I run this code using C backend, debug output is 0,0
if I use strings
when I run this code using asm backend, debug output is 0,3
if I use pointers
when I run this code using asm backend, debug output is 0,5

I discovered this trying to figure out why movefilex_() was failing
So My bigger question is why is this failing?

Code: Select all

Procedure.s GetTempFileName()
  Protected lg, tempFilename.s,tempPath.s
  tempPATH = Space( #MAX_PATH )
  lg = GetTempPath_( #MAX_PATH, tempPATH )
  tempPATH=Left( tempPATH, lg )
  
  tempFILENAME=Space( #MAX_PATH )
  GetTempFileName_( tempPATH, "huh", 0, tempFILENAME )
  debug tempFileName
  Debug FileSize( tempFilename ) ; file does exist!
  
  Debug MoveFileEx_( tempFilename, "", #MOVEFILE_DELAY_UNTIL_REBOOT ) 
  Debug GetLastError_(); C=0, asm=3 (system cannot find path specified)
  
  Debug MoveFileEx_( @tempFilename, #NUL, #MOVEFILE_DELAY_UNTIL_REBOOT ) 
  Debug GetLastError_(); C=0, asm=5 (access denied)
    
  ProcedureReturn tempFilename
EndProcedure

DeleteFile( GetTempFileName(),#PB_FileSystem_Force)
FWIW, I get this in dbgview when running this example
1259.254764 2024/04/18 04:42:45.768 5932 cc1.exe Invalid parameter passed to C runtime function.[/code]

Re: c vs asm - MoveFileEx()/GetLastError()

Posted: Thu Apr 18, 2024 1:38 pm
by PeDe
You must call GetLastError_() immediately after an error, and you must not use 'Debug ...'.

e.g.:

Code: Select all

;Debug MoveFileEx_( tempFilename, "", #MOVEFILE_DELAY_UNTIL_REBOOT ) 
;Debug GetLastError_(); C=0, asm=3 (system cannot find path specified)
If Not MoveFileEx_( tempFilename, "", #MOVEFILE_DELAY_UNTIL_REBOOT )
    Protected iError.l
    iError = GetLastError_(); C=0, asm=3 (system cannot find path specified)
    Debug iError
EndIf
This is how it works here with Windows 7 x64.

Peter

Re: c vs asm - MoveFileEx()/GetLastError()

Posted: Thu Apr 18, 2024 8:13 pm
by jassing
OK -- why does movefilex fail?
GetLastError() is called immediately after movefilex()

Re: c vs asm - MoveFileEx()/GetLastError()

Posted: Fri Apr 19, 2024 12:31 am
by Demivec
jassing wrote: Thu Apr 18, 2024 8:13 pm OK -- why does movefilex fail?
GetLastError() is called immediately after movefilex()
https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-movefileexw
Because the actual move and deletion operations specified with the MOVEFILE_DELAY_UNTIL_REBOOT flag take place after the calling application has ceased running, the return value cannot reflect success or failure in moving or deleting the file. Rather, it reflects success or failure in placing the appropriate entries into the registry.
Also, regqrding the use of the MOVEFILE_DELAY_UNTIL_REBOOT flag:
This value can be used only if the process is in the context of a user who belongs to the administrators group or the LocalSystem account.

Re: c vs asm - MoveFileEx()/GetLastError()

Posted: Fri Apr 19, 2024 6:56 am
by PeDe
jassing wrote: Thu Apr 18, 2024 8:13 pm OK -- why does movefilex fail?
GetLastError() is called immediately after movefilex()
The result of 'MoveFileEx_()' is output by 'Debug'. If an API function is called by 'Debug', the last error code for 'GetLastError_()' can be deleted.

The empty string "" for 'MoveFileEx()' is not a null string, so only #NUL, #Null$ or 0 should be used.

Peter

Re: c vs asm - MoveFileEx()/GetLastError()

Posted: Thu Apr 25, 2024 1:27 am
by jassing
using #null or #null$, C or ASM backend
MoveFileEx_() = 0
GetLastError_() = 5
So the question is why is it not? failing but failing with "access denied"?

Code: Select all

Procedure.s GetLastErrorStr( error=-999 )
  Protected Buffer.i, result.s
  If error = -999 : error = GetLastError_() : EndIf 
  If FormatMessage_( #FORMAT_MESSAGE_ALLOCATE_BUFFER | #FORMAT_MESSAGE_FROM_SYSTEM, 0, error, 0, @Buffer, 0, 0 )
    result = PeekS( Buffer ) : result=Left(result,Len(result)-SizeOf(Character))
    LocalFree_( Buffer )
  EndIf
  ProcedureReturn result
EndProcedure

Procedure.s GetTempFileName()
  Protected lg, tempFilename.s,tempPath.s
  tempPATH = Space( #MAX_PATH )
  lg = GetTempPath_( #MAX_PATH, tempPATH )
  tempPATH=Left( tempPATH, lg )
  
  tempFILENAME=Space( #MAX_PATH )
  GetTempFileName_( tempPATH, "huh", 0, tempFILENAME )
  Debug tempFileName
  Debug "Size: "+FileSize( tempFilename ) ; file does exist!
  
  x = MoveFileEx_( @tempFilename, #Null, #MOVEFILE_DELAY_UNTIL_REBOOT ) 
  z = GetLastError_()
  Debug "  MoveFileEx_() = " + x
  Debug "GetLastError_() = " + z + " (" + GetLastErrorStr(z) + ")"
  
  ProcedureReturn tempFilename
EndProcedure

DeleteFile( GetTempFileName(),#PB_FileSystem_Force)

Re: c vs asm - MoveFileEx()/GetLastError()

Posted: Thu Apr 25, 2024 11:59 am
by PeDe
As described above by Demivec, you need administrator rights. If I start PureBasic with administrator rights, your code works. Tested with Windows 10 22H2.

Here is a screenshot:
https://www.dreisiebner.at/temp/PB_MoveFileEx.png

Peter