We have wrapped a bunch of RAPI in ctypes, and will be releasing it in the next week or so to the PocketPC project.

We can read and write files, create processes, enumerate storage and directories, etc. It's a great starting place for anything else as well. I've attached it.


Copyright (c) 2002-2004, TechGame Networks, LLC.
All rights reserved.

Redistribution and use in source and binary forms, with or without 
modification, are permitted 
provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright notice, 
      this list of conditions and the following disclaimer in the documentation 
and/or 
      other materials provided with the distribution.

    * Neither the name of TechGame Networks, LLC nor the names of its 
contributors may 
      be used to endorse or promote products derived from this software without 
specific 
      prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
ANY EXPRESS 
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
MERCHANTABILITY 
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
COPYRIGHT OWNER OR 
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
SERVICES; LOSS OF USE, 
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
LIABILITY, WHETHER 
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
ARISING IN ANY WAY OUT 
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
##~ Copyright (C) 2002-2005  TechGame Networks, LLC.              ##
##~                                                               ##
##~ This library is free software; you can redistribute it        ##
##~ and/or modify it under the terms of the BSD style License as  ##
##~ found in the LICENSE file included with this distribution.    ##
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~ Imports 
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

import StringIO
import ctypes
from ctypes import sizeof, byref, c_buffer, c_ulong, c_wchar, Structure, POINTER
import win32file

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~ Constants / Variables / Etc. 
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

FAF_ATTRIBUTES               = 0x00000001;
FAF_CREATION_TIME            = 0x00000002;
FAF_LASTACCESS_TIME          = 0x00000004;
FAF_LASTWRITE_TIME           = 0x00000008;
FAF_SIZE_HIGH                = 0x00000010;
FAF_SIZE_LOW                 = 0x00000020;
FAF_OID                      = 0x00000040;
FAF_NAME                     = 0x00000080;

FAF_FLAG_COUNT               = 8;

FAF_ATTRIB_CHILDREN          = 0x00001000;
FAF_ATTRIB_NO_HIDDEN         = 0x00002000;
FAF_FOLDERS_ONLY             = 0x00004000;
FAF_NO_HIDDEN_SYS_ROMMODULES = 0x00008000;

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~ Definitions 
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

MAX_PATH = 260

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

class RAPIINIT(Structure):
    _fields_ = [
        ('cbSize', c_ulong),
        ('heRapiInitEvent', c_ulong),
        ('hrRapiInit', c_ulong), ]

class FILETIME(Structure):
    _fields_ = [
        ('nTimeHigh', c_ulong),
        ('nTimeLow', c_ulong), ]

class CE_FIND_DATA(Structure):
    _fields_ = [
        ('dwFileAttributes', c_ulong),
        ('ftCreationTime', FILETIME),
        ('dwLastAccessTime', FILETIME),
        ('dwLastWriteTime', FILETIME),
        ('nFileSizeHigh', c_ulong),
        ('nFileSizeLow', c_ulong),
        ('dwOID', c_ulong),
        ('cFileName', c_wchar*MAX_PATH), ]

class PROCESS_INFORMATION(Structure):
    _fields_ = [
        ('hProcess', c_ulong), 
        ('hThread', c_ulong), 
        ('dwProcessId', c_ulong), 
        ('dwThreadId', c_ulong), ]

class PocketRapi(object):
    blockSize=65536
    _rapiReady = False
    _heRapiInitEvent = None

    def __init__(self, blocking=False):
        if blocking is not None:
            self.init(blocking)

    def __nonzero__(self):
        return self.isReady()

    def init(self, blocking=False):
        if blocking:
            self._rapiReady = (self.rapi().CeRapiInit() == 0) # S_OK == 0
            return self._rapiReady

        self._rapiReady = None
        args = RAPIINIT()
        args.cbSize = sizeof(args)
        self.rapi().CeRapiInitEx(byref(args))
        if args.hrRapiInit == 0: # S_OK
            self._heRapiInitEvent = args.heRapiInitEvent
            return True
        else: return False

    def isReady(self, timeout=0):
        if not self._rapiReady and self._heRapiInitEvent:
            self.waitForInit(timeout)
        return bool(self._rapiReady)

    def waitForInit(self, timeout=0):
        if not self._heRapiInitEvent:
            raise OSError("Event not initialized")

        miliseconds = min(0, max(int(timeout*1000), 0x7fffffff))
        events = (c_ulong*1)(self._heRapiInitEvent)
        waitResult = self.user32().MsgWaitForMultipleObjects(len(events), events, False, miliseconds, 0)

        if waitResult == 0:
            self._heRapiInitEvent = None
            self._rapiReady = True
        return self._rapiReady

    def uninit(self):
        self.rapi().CeRapiUninit()
        self._rapiReady = False

    def getRapiError(self):
        if self.rapi().CeRapiGetError() == 0:
            return self.rapi().CeGetLastError()
        return None

    @staticmethod
    def user32(): 
        return ctypes.windll.user32

    @staticmethod
    def rapi(): 
        return ctypes.windll.rapi

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    def rmFile(self, path):
        return self.rapi().CeDeleteFile(unicode(path))

    def mkDir(self, path):
        return self.rapi().CeCreateDirectory(unicode(path), None)
    def rmDir(self, path):
        return self.rapi().CeRemoveDirectory(unicode(path))

    def findFiles(self, path, incAttrs=False):
        mask = FAF_NAME  # Fill in the filename field
        if incAttrs:
            mask |= FAF_ATTRIBUTES # fill in the attribute field
            mask |= FAF_SIZE_LOW | FAF_SIZE_HIGH

        result = []
        nCount = c_ulong(0)
        answer = POINTER(CE_FIND_DATA*32767)()
        try:
            self.rapi().CeFindAllFiles(unicode(path), mask, byref(nCount), byref(answer))

            if answer:
                answer = answer[0] # deref the pointer
                for i in xrange(nCount.value):
                    a = answer[i]
                    if incAttrs:
                        result.append((a.cFileName, (a.nFileSizeHigh << 32) | a.nFileSizeLow, a.dwFileAttributes))
                    else:
                        result.append(a.cFileName)
        finally:
            # free the memory they allocated for us
            if answer:
                self.rapi().CeRapiFreeBuffer(byref(answer))
        return result
    
    def copyFileToDevice(self, hostFile, toPath,):
        if isinstance(hostFile, (str, unicode)):
            hostFile = open(hostFile, 'rb')

        #HANDLE CeCreateFile(
        #            LPCWSTR lpFileName, 
        #            DWORD dwDesiredAccess, 
        #            DWORD dwShareMode, 
        #            LPSECURITY_ATTRIBUTES lpSecurityAttributes, 
        #            DWORD dwCreationDisposition, 
        #            DWORD dwFlagsAndAttributes, 
        #            HANDLE hTemplateFile); 

        hceFile = self.rapi().CeCreateFile(unicode(toPath), win32file.GENERIC_WRITE, win32file.FILE_SHARE_READ, None, win32file.CREATE_ALWAYS, win32file.FILE_ATTRIBUTE_NORMAL, 0)
        if hceFile == win32file.INVALID_HANDLE_VALUE:
            raise OSError("Error creating file on the device")

        try:
            dwWritten = c_ulong(0)
            data = hostFile.read(self.blockSize)
            while data:
                while dwWritten.value < len(data):
                    dwWritten.value = 0
                    self.rapi().CeWriteFile(hceFile, data, len(data), byref(dwWritten), None)
                    data = data[dwWritten.value:]

                dwWritten.value = 0
                data = hostFile.read(self.blockSize)
        finally:
            self.rapi().CeCloseHandle(hceFile)

    def getAttrs(self, path):
        result = self.rapi().CeGetFileAttributes(unicode(path))
        if result == -1: 
            return None
        else: return result
    def exists(self, path):
        return self.getAttrs(path) is not None
    def dirExists(self, path):
        return self.getAttrs(path) is not None
    def fileExists(self, path):
        return self.getAttrs(path) is not None

    def readFile(self, fromPath):
        hostFile = StringIO.StringIO()
        self.copyFileFromDevice(fromPath, hostFile)
        hostFile.seek(0)
        return hostFile

    def copyFileFromDevice(self, fromPath, hostFile):
        if isinstance(hostFile, (str, unicode)):
            hostFile = open(hostFile, 'wb')

        hceFile = self.rapi().CeCreateFile(unicode(fromPath), win32file.GENERIC_READ, win32file.FILE_SHARE_READ, None, win32file.OPEN_EXISTING, win32file.FILE_ATTRIBUTE_NORMAL, 0)
        if hceFile == win32file.INVALID_HANDLE_VALUE:
            raise OSError("Error opening the file on the device for reading")

        try:
            dwRead = c_ulong(1)
            data = (self.blockSize * ctypes.c_char)()
            
            while dwRead.value:
                dwRead.value = 0
                self.rapi().CeReadFile(hceFile, data, len(data), byref(dwRead), None)
                hostFile.write(data.raw[:dwRead.value])
        finally:
            self.rapi().CeCloseHandle(hceFile)
        return hostFile
    
    def popenDevice(self, path, commandLine=u''):
        processInfo = PROCESS_INFORMATION()
        result = bool(self.rapi().CeCreateProcess(unicode(path), unicode(commandLine), None, None, False, 0, None, None, None, byref(processInfo)))
        return result


On Jan 9, 2006, at 9:00 AM, Luke Dunstan wrote:


----- Original Message ----- From: "Thomas Heller" <[EMAIL PROTECTED]>
To: <pythonce@python.org>
Sent: Monday, January 09, 2006 10:42 PM
Subject: Re: [PythonCE] How do you develop on the PocketPC?


"Luke Dunstan" <[EMAIL PROTECTED]> writes:

I'm sorry to say that I've seen the NULL bug before but have been too
distracted by the task at hand to fix it, but here is a patch that
fixes it.

By the way, I've recently tried running the remote part of "winpdb"
(http://www.digitalpeers.com/pythondebugger/) on Windows CE and
connecting to it over TCP/IP from the GUI running on the PC, and after
a trivial change (to handle a lack of PATH environment variable) it
worked fine. Personally I would rather have the ability to communicate
to the remote debugger using ActiveSync rather than only TCP/IP
because it is more convenient especially since I only have Bluetooth
not WiFi, so I have been investigating using the Remote API (RAPI).

In case you are talking about the scripts I posted: Although the client and server connect via TCP/IP, the only connection between the pockect PC and the desktop computer I have is the cradle with an USB cable, plus activesync (3.8, IIRC) running. It seems activesync emulates internet
connection on the pocket pc.

Thomas

I have noticed that IE works on the PDA when cradled, but I know that ActiveSync is not providing a real network adapter on the PC side because an extra IP does not appear in the output of 'ipconfig'. This prevents running TCP listen servers on the PDA but it is true that your method works nicely in this case. As a demonstration of how we could make it even more convenient, I have modified it slightly so that the server starts the client script on the PDA remotely, using RAPI via ctypes. I have put the experimental RAPI interfacing code in a separate module "wincerapi".

We should probably consider putting all these scripts in CVS somewhere.

Luke
<pyceserver.py>
<wincerapi.py>
_______________________________________________
PythonCE mailing list
PythonCE@python.org
http://mail.python.org/mailman/listinfo/pythonce

_______________________________________________
PythonCE mailing list
PythonCE@python.org
http://mail.python.org/mailman/listinfo/pythonce

Reply via email to