2012-01-05 20 views
5

के साथ फ़ंक्शन तर्क के रूप में एक स्ट्रक्चर का उपयोग करना, इसलिए मैं एक पायथन सी-एक्सटेंशन पोर्ट करने का प्रयास कर रहा हूं जिसे मैंने विंडोज़ पर जंक्शन/प्रतीकात्मक लिंक/इत्यादि को शुद्ध पायथन पर ctypes मॉड्यूल का उपयोग करके लिखा है। दुर्भाग्यवश, चूंकि मेरे पिछले प्रकार के उपयोग बहुत सीमित हैं, मुझे लगता है कि मैं कहीं गलती कर रहा हूं जिससे मेरा कोड गलत तरीके से काम कर रहा है। यहां मेरे पास अब तक है:पायथन सीटीपीएस मॉड्यूल

from os import path 
from ctypes import * 
from ctypes.wintypes import * 

# Python implementation of: 
# 
# typedef struct { 
#  DWORD ReparseTag; 
#  DWORD ReparseDataLength; 
#  WORD Reserved; 
#  WORD ReparseTargetLength; 
#  WORD ReparseTargetMaximumLength; 
#  WORD Reserved1; 
#  WCHAR ReparseTarget[1]; 
# } REPARSE_MOUNTPOINT_DATA_BUFFER, *PREPARSE_MOUNTPOINT_DATA_BUFFER; 

class ReparsePoint(Structure): 
    _fields_ = [ 
     ("ReparseTag", DWORD), 
     ("ReparseDataLength", DWORD), 
     ("Reserved", WORD), 

     ("ReparseTargetLength", WORD), 
     ("ReparseTargetMaximumLength", WORD), 
     ("Reserved1", WORD), 
     ("ReparseTarget", c_wchar_p), 
    ] 

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 

IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003 
REPARSE_MOUNTPOINT_HEADER_SIZE = 8 

FSCTL_SET_REPARSE_POINT = 589988 
FILE_FLAG_OPEN_REPARSE_POINT = 2097152 
FILE_FLAG_BACKUP_SEMANTICS = 33554432 
FILE_FLAG_REPARSE_BACKUP = 35651584 # FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS 

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 CreateDirectory(fpath): 
    return windll.kernel32.CreateDirectoryW(LPWSTR(fpath), LPSECURITY_ATTRIBUTES(NULL)) != FALSE 

def RemoveDirectory(fpath): 
    return windll.kernel32.RemoveDirectoryW(LPWSTR(fpath)) != FALSE 

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 

def junction(source, link_name): 
    """ Create a junction at link_name pointing to source directory. """ 
    if not path.isdir(source): 
     raise Exception('Junction source does not exist or is not a directory.') 

    link_name = path.abspath(link_name) 
    if path.exists(link_name): 
     raise Exception('Filepath for new junction already exists.') 

    if not CreateDirectory(link_name): 
     raise Exception('Failed to create new directory for target junction.') 

    source = translate_path(source) 
    hFile = CreateFile(link_name, GENERIC_WRITE, 0, OPEN_EXISTING, FILE_FLAG_REPARSE_BACKUP) 
    if hFile == HANDLE(INVALID_HANDLE_VALUE): 
     raise Exception('Failed to open directory for junction creation.') 

    datalen = len(source) * sizeof(c_wchar) 
    reparseInfo = ReparsePoint(
     IO_REPARSE_TAG_MOUNT_POINT, 
     datalen + 12, 
     0, 
     datalen, 
     datalen + sizeof(c_wchar), 
     0, 
     source 
    ) 
    pReparseInfo = pointer(reparseInfo) 

    print reparseInfo.ReparseTarget 
    returnedLength = DWORD(0) 
    result = BOOL(
     windll.kernel32.DeviceIoControl(
      hFile, 
      DWORD(FSCTL_SET_REPARSE_POINT), 
      pReparseInfo, 
      DWORD(reparseInfo.ReparseDataLength + REPARSE_MOUNTPOINT_HEADER_SIZE), 
      LPVOID(NULL), 
      DWORD(0), 
      byref(returnedLength), 
      LPOVERLAPPED(NULL) 
     ) 
    ) == TRUE 

    #if not result: 
     #RemoveDirectory(link_name) 

    windll.kernel32.CloseHandle(hFile) 
    return result 

print junction('G:\\cpp.workspace\\tools', 'test') 
""" 
Just putting this here for the moment so I know how to call the function. 

BOOL WINAPI DeviceIoControl(
    __in   HANDLE hDevice, 
    __in   DWORD dwIoControlCode, 
    __in_opt  LPVOID lpInBuffer, 
    __in   DWORD nInBufferSize, 
    __out_opt LPVOID lpOutBuffer, 
    __in   DWORD nOutBufferSize, 
    __out_opt LPDWORD lpBytesReturned, 
    __inout_opt LPOVERLAPPED lpOverlapped 
); 
""" 

वर्तमान में जब चलाया जाता है, तो कोड लक्ष्य जंक्शन के लिए एक फ़ोल्डर बनाता है। (इस मामले में, परीक्षण) यह सिस्टम को सिग्नल करने के लिए रिपेर्स टैग भी लागू कर रहा है कि फ़ोल्डर एक जंक्शन है। हालांकि, "जी: \ cpp.workspace \ tools" (या बल्कि, \ ?? \ g: \ cpp.workspace \ tools) को इंगित करने के बजाय, जंक्शन इंगित करता है: 㢨 \ 獬

अब, जाहिर है यह reparseInfo.ReparseTarget के साथ एक मुद्दा है, लेकिन मैं यह पता लगाने में असमर्थ हूं कि मैंने क्या किया है।

#  WCHAR ReparseTarget[1]; 

[1] भ्रामक है, एपीआई struct के अंत में एक अशक्त-समाप्त स्ट्रिंग की उम्मीद:

उत्तर

3

यह WCHAR की एक सरणी, नहीं सूचक है।

+0

धन्यवाद। RepeseTarget को c_wchar * MAX_PATH (MAX_PATH 260) में बदलकर काम कर रहा है, फिर DeviceIoControl कॉल से पहले reparseInfo._fields_ [6] = ('ReparseTarget', datalen) जोड़ना। –

संबंधित मुद्दे