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