2

I am following this tutorials here where the CopyFile function calling the windows API just dosen't work for me. This is the code I am using (just changed the username)

from ctypes import *
CopyFile = windll.kernel32.CopyFileA
CopyFile("C:\Windows\System32\calc.exe", "C:\\Users\legion\Desktop\calc.exe", False)

I tried changing the parameters, file path, I tried same file to the same directory changing False to True so that I may get an error or prompt that the file already exists. It just dosen't work. If you haven't worked with Ctypes (like me) and don't know the answer, please try and try this snippet on your machine.

1 Answers1

2

The 1st thing that I see, is that some backslashes (\) in the paths are not escaped. It won't be a problem in this particular case, but it's better to always escape them.

I modified your code a bit.

code00.py

#!/usr/bin/env python

import ctypes as ct
import os
import sys


def main(*argv):
    src = r"C:\Windows\System32\calc.exe"
    dst = os.path.join(os.getcwd(), "calc.exe")

    kernel32 = ct.windll.kernel32
    copy_file_a = kernel32.CopyFileA
    copy_file_w = kernel32.CopyFileW

    reta = copy_file_a(src, dst, False)
    retw = copy_file_w(src, dst, False)

    print("{:s} returned: {:d}\n{:s} returned: {:d}\n".format(copy_file_a.__name__, reta, copy_file_w.__name__, retw))


if __name__ == "__main__":
    print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
                                                   64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    rc = main(*sys.argv[1:])
    print("\nDone.")
    sys.exit(rc)

Output:

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q048927571]> "e:\Work\Dev\VEnvs\py_pc064_02.07.18_test0\Scripts\python.exe" code00.py
Python 2.7.18 (v2.7.18:8d21aa21f2, Apr 20 2020, 13:25:05) [MSC v.1500 64 bit (AMD64)] 064bit on win32

CopyFileA returned: 1
CopyFileW returned: 0


Done.

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q048927571]> "e:\Work\Dev\VEnvs\py_pc064_03.09_test0\Scripts\python.exe" code00.py
Python 3.9.9 (tags/v3.9.9:ccb0e6a, Nov 15 2021, 18:08:50) [MSC v.1929 64 bit (AMD64)] 064bit on win32

CopyFileA returned: 0
CopyFileW returned: 1


Done.

Notes:

  • According to [MS.Docs]: CopyFile function:

    If the function succeeds, the return value is nonzero.

  • I've added CopyFileW in the mix

  • According to output, CopyFileA fails with Python 3 (I've figured out that this is your scenario), and CopyFileW fails with Python 2.
    That happens because in Python 2, strings are 008bit (char * based), while in Python 3 they are Unicode (016bit (wchar_t * based) on Win).
    Check [SO]: Passing utf-16 string to a Windows function (@CristiFati's answer) for more details

  • Since the ANSI (A) version of a function has some limitations compared to its Wide (W) version, it's recommended to use the latter one

We have a cause for the failure, but we're not quite there yet. Here's a more elaborate example.

code01.py:

#!/usr/bin/env python

import ctypes as ct
import os
import sys


def main(*argv):
    src = r"C:\Windows\System32\calc.exe"
    dst = os.path.join(os.getcwd(), "calc.exe")

    kernel32 = ct.windll.kernel32

    copy_file_a = kernel32.CopyFileA
    copy_file_a.argtypes = (ct.c_char_p, ct.c_char_p, ct.c_int)
    copy_file_a.restype = ct.c_int

    copy_file_w = kernel32.CopyFileW
    copy_file_w.argtypes = (ct.c_wchar_p, ct.c_wchar_p, ct.c_int)
    copy_file_w.restype = ct.c_int

    reta = copy_file_a(src.encode(), dst.encode(), False)
    retw = copy_file_w(src, dst, False)

    print("{:s} returned: {:d}\n{:s} returned: {:d}\n".format(copy_file_a.__name__, reta, copy_file_w.__name__, retw))


if __name__ == "__main__":
    print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
                                                   64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    rc = main(*sys.argv[1:])
    print("\nDone.")
    sys.exit(rc)

Notes:

Output:

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q048927571]> "e:\Work\Dev\VEnvs\py_pc064_02.07.18_test0\Scripts\python.exe" code01.py
Python 2.7.18 (v2.7.18:8d21aa21f2, Apr 20 2020, 13:25:05) [MSC v.1500 64 bit (AMD64)] 064bit on win32

CopyFileA returned: 1
CopyFileW returned: 1


Done.

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q048927571]> "e:\Work\Dev\VEnvs\py_pc064_03.09_test0\Scripts\python.exe" code01.py
Python 3.9.9 (tags/v3.9.9:ccb0e6a, Nov 15 2021, 18:08:50) [MSC v.1929 64 bit (AMD64)] 064bit on win32

CopyFileA returned: 1
CopyFileW returned: 1


Done.
CristiFati
  • 38,250
  • 9
  • 50
  • 87