0

I'm trying to reproduce similar thing as in On Windows, how to open for writing a file already opened for writing by another process? so I followed the answer by Piotr Dobrogost, modyfing the code from Using a struct as a function argument with the python ctypes module, changing the flags and attributes to my purposes (taken from here https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx and here http://unix.superglobalmegacorp.com/Net2/newsrc/sys/fcntl.h.html) and adding the Python (using 3.3 version) open function: from os import path from ctypes import * from ctypes.wintypes import *

GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000

FILE_SHARE_DELETE = 0x00000004
FILE_SHARE_READ = 0x00000001
FILE_SHARE_WRITE = 0x00000002
FILE_SHARE_READ_WRITE = (FILE_SHARE_READ | FILE_SHARE_WRITE)

OPEN_EXISTING = 3

FILE_ATTRIBUTE_NORMAL = 128
FILE_ATTRIBUTE_TEMPORARY = 256

O_RDONLY =  0x0000      # open for reading only 
O_WRONLY = 0x0001       # open for writing only 
O_RDWR = 0x0002     # open for reading and writing 
O_ACCMODE = 0x0003      # mask for above modes 
O_APPEND = 0x0008       # set append mode 

INVALID_HANDLE_VALUE = -1
LPOVERLAPPED = c_void_p
LPSECURITY_ATTRIBUTES = c_void_p

NULL = 0
FALSE = BOOL(0)
TRUE = BOOL(1)

def CreateFile(filename, access, sharemode, creation, flags):
    return HANDLE(windll.kernel32.CreateFileW(
        LPWSTR(filename),
        DWORD(access),
        DWORD(sharemode),
        LPSECURITY_ATTRIBUTES(NULL),
        DWORD(creation),
        DWORD(flags),
        HANDLE(NULL)
    ))


def translate_path(fpath):
    fpath = path.abspath(fpath)
    if fpath[len(fpath)-1] == '\\' and fpath[len(fpath)-2] == ':':
        fpath = fpath[:len(fpath)-1]
    return '\\??\\%s' % fpath

link_name = 'G:\\MATLAB\\Chronos_Python\\test.txt'
link_name = path.abspath(link_name)

hFile = CreateFile(link_name, GENERIC_READ, FILE_SHARE_WRITE, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL)

if hFile == HANDLE(INVALID_HANDLE_VALUE):
   raise Exception('Failed to open directory for junction creation.')

cFile = ctypes.cdll.msvcrt._open_osfhandle(hFile,O_RDONLY)
pyFile = open(cFile,'r')
pyFile.read()
pyFile.close()
ctypes.cdll.msvcrt._close(cFile)

windll.kernel32.CloseHandle(hFile)

but at the line pyFile = open(cFile,'r') I get

OSError: [Errno 9] Bad file descriptor

It might be something very basic, since I am a newbie to python... I'd very much appreciate if someone could help me fix it.

Community
  • 1
  • 1
Remolek
  • 1
  • 1
  • The biggest mistake here is calling the `_open_osfhandle` function in msvcrt.dll -- the private C runtime of Windows system DLLs (much abused by MinGW). This CRT has nothing to do with CPython. You should be using Python's `msvcrt` module to assign the file descriptor. – Eryk Sun Dec 07 '16 at 04:45
  • @eryksun Thank you! I've used `msvcrt.open_osfhandle(hFile.value,O_RDONLY)` (I had to use `.value` to get `int` type, because otherwise I was getting TypeError), and now it works. – Remolek Dec 08 '16 at 17:42

1 Answers1

1

Assuming the handle to the file was properly generated, I think your issue might be here:

pyFile = open(cFile,'r')

You're trying to open a C run-time file descriptor, so you'll need to use the fdopen function in python:

pyFile = os.fdopen(cFile, 'r')

You might want to look at the documentation here - python exposes some of the msvcrt functions through the standard library on Windows: https://docs.python.org/3.6/library/msvcrt.html#msvcrt.open_osfhandle

iUknwn
  • 322
  • 2
  • 9