Re: How do you develop on the PocketPC?

Brian Brown <[email protected]>
Newsgroups gmane.comp.python.windows-ce
Message-ID <[email protected]>
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.



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

>
> ----- Original Message ----- From: "Thomas Heller"  
> <[email protected]>
> To: <[email protected]>
> 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
> [email protected]
> http://mail.python.org/mailman/listinfo/pythonce

_______________________________________________
PythonCE mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pythonce
LICENSE.txt (text/plain, 1.5 KB)
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.
pocketRapi.py (text/x-python-script, 8.3 KB)
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
##~ 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.