Hey Everyone,
Just thought I'd upload our latest RAPI code that implements a file
like object for reading and writing over RAPI. Hope you all find it
helpful! Currently, it doesn't support the readline and iterator
type thing, though that should be doable on top of this interface.
Just didn't have time to tackle that piece when I was writing it.
Enjoy!
-Shane & Brian
#!/usr/bin/env python
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
##~ 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 os
from ctypes import windll, FormatError, sizeof, byref
from ctypes import c_buffer, c_ulong, c_char, c_wchar, Structure, POINTER
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~ Constants / Variables / Etc.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
INVALID_HANDLE_VALUE = -1
GENERIC_EXECUTE = 0x20000000
GENERIC_WRITE = 0x40000000
GENERIC_READ =-0x80000000
CREATE_NEW = 0x1
CREATE_ALWAYS = 0x2
OPEN_EXISTING = 0x3
OPEN_ALWAYS = 0x4
FILE_SHARE_READ = 0x1
FILE_SHARE_WRITE = 0x2
FILE_SHARE_DELETE = 0x4
FILE_FLAG_POSIX_SEMANTICS = 0x01000000
FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
FILE_FLAG_DELETE_ON_CLOSE = 0x04000000
FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000
FILE_FLAG_RANDOM_ACCESS = 0x10000000
FILE_FLAG_NO_BUFFERING = 0x20000000
FILE_FLAG_OVERLAPPED = 0x40000000
FILE_FLAG_WRITE_THROUGH =-0x80000000
FILE_ATTRIBUTE_READONLY = 0x0001
FILE_ATTRIBUTE_HIDDEN = 0x0002
FILE_ATTRIBUTE_SYSTEM = 0x0004
FILE_ATTRIBUTE_DIRECTORY = 0x0010
FILE_ATTRIBUTE_ARCHIVE = 0x0020
FILE_ATTRIBUTE_NORMAL = 0x0080
FILE_ATTRIBUTE_TEMPORARY = 0x0100
FILE_ATTRIBUTE_COMPRESSED = 0x0800
FILE_ATTRIBUTE_OFFLINE = 0x1000
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~ WinCE File-like object
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class CEFile(object):
name = None
mode = None
closed = True
newlines = None
softspace = 0
raiseErrors = True
_flagShare = FILE_SHARE_READ
_flagAttribute = FILE_ATTRIBUTE_NORMAL
_flagWriteThrough = 0
def __init__(self, name, mode='rU', buffering=None):
self._loadRapiMethods()
mode = mode.lower()
self.name = name
self.mode = mode
if buffering == 0:
self._flagWriteThrough = 1
if 'u' in mode:
self.newlines = ['\r\n']
if 'a' in mode:
openMethod = self._openAppend
fileAccessMode = GENERIC_WRITE
elif 'w' in mode:
openMethod = self._openWrite
fileAccessMode = GENERIC_WRITE
elif 'r' in mode:
openMethod = self._openRead
fileAccessMode = GENERIC_READ
if '+' in mode:
fileAccessMode = GENERIC_READ | GENERIC_WRITE
self._handle = openMethod(name, fileAccessMode)
self.closed = False
def __repr__(self):
return "<%s.%s '%s', mode '%s' at 0x%x>" % (
self.__class__.__module__, self.__class__.__name__,
self.name, self.mode, id(self))
_isCELoaded = False
@classmethod
def _loadRapiMethods(klass):
if klass._isCELoaded:
return True
rapi = windll.rapi
klass._CeGetLastError_ = staticmethod(rapi.CeGetLastError)
def CeErrorCheck(result, cfunc, args):
ceErrorNo = klass._CeGetLastError_()
if ceErrorNo and ceErrorNo != 183:
if klass.raiseErrors:
raise IOError('%s %d (0x%x)' % (FormatError(ceErrorNo), ceErrorNo, ceErrorNo))
else:
print IOError('%s %d (0x%x)' % (FormatError(ceErrorNo), ceErrorNo, ceErrorNo))
return result
klass._CeCreateFile_ = staticmethod(rapi.CeCreateFile)
klass._CeCreateFile_.errcheck = CeErrorCheck
klass._CeCloseHandle_ = staticmethod(rapi.CeCloseHandle)
klass._CeCloseHandle_.errcheck = CeErrorCheck
klass._CeSetFilePointer_ = staticmethod(rapi.CeSetFilePointer)
klass._CeSetFilePointer_.errcheck = CeErrorCheck
klass._CeGetFileSize_ = staticmethod(rapi.CeGetFileSize)
klass._CeGetFileSize_.errcheck = CeErrorCheck
klass._CeReadFile_ = staticmethod(rapi.CeReadFile)
klass._CeReadFile_.errcheck = CeErrorCheck
klass._CeWriteFile_ = staticmethod(rapi.CeWriteFile)
klass._CeWriteFile_.errcheck = CeErrorCheck
klass._CeSetEndOfFile_ = staticmethod(rapi.CeSetEndOfFile)
klass._CeSetEndOfFile_.errcheck = CeErrorCheck
klass._isCELoaded = True
return True
def _openRead(self, name, fileAccessMode=GENERIC_READ):
hceFile = self._CeCreateFile_(
unicode(name),
fileAccessMode,
self._flagShare,
None,
OPEN_EXISTING,
self._flagAttribute,
self._flagWriteThrough and FILE_FLAG_WRITE_THROUGH or 0)
if hceFile == INVALID_HANDLE_VALUE:
raise IOError("Error opening the file on the device for reading")
return hceFile
def _openAppend(self, name, fileAccessMode=GENERIC_WRITE):
hceFile = self._CeCreateFile_(
unicode(name),
fileAccessMode,
self._flagShare,
None,
OPEN_ALWAYS,
self._flagAttribute,
self._flagWriteThrough and FILE_FLAG_WRITE_THROUGH or 0)
if hceFile == INVALID_HANDLE_VALUE:
raise IOError("Error opening file on the device for appending")
return hceFile
def _openWrite(self, name, fileAccessMode=GENERIC_WRITE):
hceFile = self._CeCreateFile_(
unicode(name),
GENERIC_WRITE,
self._flagShare,
None,
CREATE_ALWAYS,
self._flagAttribute,
self._flagWriteThrough and FILE_FLAG_WRITE_THROUGH or 0)
if hceFile == INVALID_HANDLE_VALUE:
raise IOError("Error opening file on the device for writing")
return hceFile
def close(self):
self._CeCloseHandle_(self._getHandle())
self._handle = None
self.closed = True
def isatty(self):
return False
def fileno(self):
return None
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def tell(self):
return self.seek(0, 1)
def seek(self, pos, whence=0):
result = self._CeSetFilePointer_(self._getHandle(), pos, None, whence)
if result == 0xffffffff:
raise IOError('CE Seek Error')
return result
def flush(self,):
pass
def read(self, count=None):
handle = self._getHandle()
if count is None:
count = self._CeGetFileSize_(handle, None)
data = c_buffer(count)
dwRead = c_ulong(0)
self._CeReadFile_(handle, data, len(data), byref(dwRead), None)
data = data[:dwRead.value]
if self.newlines:
for n in self.newlines:
data = data.replace(n, '\n')
return data
def writelines(self, lines):
for line in lines:
self.write(line + '\n')
def write(self, data):
if not data: return
dwWritten = c_ulong(0)
self._CeWriteFile_(self._getHandle(), data, len(data), byref(dwWritten), None)
def truncate(self, size=None):
self._CeSetEndOfFile_(self._getHandle())
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def _getHandle(self):
handle = self._handle
if handle is None or self.closed:
raise IOError("CE file handle is closed")
return handle
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~ Main
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if __name__=='__main__':
from pocketRapi import PocketRapi
pr = PocketRapi()
f = CEFile('/testfile.txt', 'a+u')
print repr(f.read())
print >> f, 'test string!'
print >> f, 'left',
print >> f, 'right'
print f.tell(), f.seek(0)
print repr(f.read())
print f.seek(0), f.seek(0, 2)
print repr(f.read())
f.close()
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
##~ 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
from ctypes import windll, FormatError, sizeof, byref
from ctypes import c_buffer, c_ulong, c_char, c_wchar, Structure, POINTER
from ceFile import CEFile
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#~ Constants / Variables / Etc.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
INVALID_HANDLE_VALUE = -1
GENERIC_EXECUTE = 0x20000000
GENERIC_WRITE = 0x40000000
GENERIC_READ =-0x80000000
CREATE_NEW = 0x1
CREATE_ALWAYS = 0x2
OPEN_EXISTING = 0x3
OPEN_ALWAYS = 0x4
FILE_SHARE_READ = 0x1
FILE_SHARE_WRITE = 0x2
FILE_SHARE_DELETE = 0x4
FILE_FLAG_POSIX_SEMANTICS = 0x01000000
FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
FILE_FLAG_DELETE_ON_CLOSE = 0x04000000
FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000
FILE_FLAG_RANDOM_ACCESS = 0x10000000
FILE_FLAG_NO_BUFFERING = 0x20000000
FILE_FLAG_OVERLAPPED = 0x40000000
FILE_FLAG_WRITE_THROUGH =-0x80000000
FILE_ATTRIBUTE_READONLY = 0x0001
FILE_ATTRIBUTE_HIDDEN = 0x0002
FILE_ATTRIBUTE_SYSTEM = 0x0004
FILE_ATTRIBUTE_DIRECTORY = 0x0010
FILE_ATTRIBUTE_ARCHIVE = 0x0020
FILE_ATTRIBUTE_NORMAL = 0x0080
FILE_ATTRIBUTE_TEMPORARY = 0x0100
FILE_ATTRIBUTE_COMPRESSED = 0x0800
FILE_ATTRIBUTE_OFFLINE = 0x1000
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 CEFileEx(CEFile):
raiseErrors = False
class PocketRapi(object):
blockSize=65536
_rapiReady = False
_heRapiInitEvent = None
raiseErrors = False
CEFile = CEFileEx
def __init__(self, blocking=False):
self._loadRapiMethods()
if blocking is not None:
self.init(blocking)
def __nonzero__(self):
return self.isReady()
def init(self, blocking=False):
if blocking:
self._rapiReady = (self._CeRapiInit_() == 0) # S_OK == 0
return self._rapiReady
self._rapiReady = None
args = RAPIINIT()
args.cbSize = sizeof(args)
self._CeRapiInitEx_(byref(args))
if args.hrRapiInit == 0: # S_OK
self._heRapiInitEvent = args.heRapiInitEvent
return True
else: return False
_isCELoaded = False
@classmethod
def _loadRapiMethods(klass):
if klass._isCELoaded:
return True
rapi = windll.rapi
klass._CeGetLastError = staticmethod(rapi.CeGetLastError)
def CeErrorCheck(result, cfunc, args):
ceErrorNo = rapi.CeGetLastError()
if ceErrorNo and ceErrorNo != 183:
if klass.raiseErrors:
raise OSError('%s %d (0x%x)' % (FormatError(ceErrorNo), ceErrorNo, ceErrorNo))
else:
print OSError('%s %d (0x%x)' % (FormatError(ceErrorNo), ceErrorNo, ceErrorNo))
return result
klass._CeCloseHandle_ = staticmethod(rapi.CeCloseHandle)
klass._CeCloseHandle_.errcheck = CeErrorCheck
klass._CeCreateDirectory_ = staticmethod(rapi.CeCreateDirectory)
klass._CeCreateDirectory_.errcheck = CeErrorCheck
klass._CeCreateFile_ = staticmethod(rapi.CeCreateFile)
klass._CeCreateFile_.errcheck = CeErrorCheck
klass._CeCreateProcess_ = staticmethod(rapi.CeCreateProcess)
klass._CeCreateProcess_.errcheck = CeErrorCheck
klass._CeDeleteFile_ = staticmethod(rapi.CeDeleteFile)
klass._CeDeleteFile_.errcheck = CeErrorCheck
klass._CeFindAllFiles_ = staticmethod(rapi.CeFindAllFiles)
klass._CeFindAllFiles_.errcheck = CeErrorCheck
klass._CeGetFileAttributes_ = staticmethod(rapi.CeGetFileAttributes)
#klass._CeGetFileAttributes_.errcheck = CeErrorCheck
klass._CeRapiFreeBuffer_ = staticmethod(rapi.CeRapiFreeBuffer)
klass._CeRapiFreeBuffer_.errcheck = CeErrorCheck
klass._CeRapiGetError_ = staticmethod(rapi.CeRapiGetError)
klass._CeRapiGetError_.errcheck = CeErrorCheck
klass._CeRapiInit_ = staticmethod(rapi.CeRapiInit)
klass._CeRapiInit_.errcheck = CeErrorCheck
klass._CeRapiInitEx_ = staticmethod(rapi.CeRapiInitEx)
#klass._CeRapiInitEx_.errcheck = CeErrorCheck
klass._CeRapiUninit_ = staticmethod(rapi.CeRapiUninit)
#klass._CeRapiUninit_.errcheck = CeErrorCheck
klass._CeReadFile_ = staticmethod(rapi.CeReadFile)
klass._CeReadFile_.errcheck = CeErrorCheck
klass._CeRemoveDirectory_ = staticmethod(rapi.CeRemoveDirectory)
klass._CeRemoveDirectory_.errcheck = CeErrorCheck
klass._CeWriteFile_ = staticmethod(rapi.CeWriteFile)
klass._CeWriteFile_.errcheck = CeErrorCheck
klass._isCELoaded = True
return True
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._CeRapiUninit_()
self._rapiReady = False
def getRapiError(self):
return self._CeGetLastError_() or None
def getRapiErrorStr(self):
return FormatError(self.getRapiError())
def joinPath(self, *args):
args = filter(None, args)
return '\\'.join(args or '')
@staticmethod
def user32():
return windll.user32
@staticmethod
def rapi():
return windll.rapi
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def rmFile(self, path):
return self._CeDeleteFile_(unicode(path))
def mkDir(self, path):
return self._CeCreateDirectory_(unicode(path), None)
def rmDir(self, path):
return self._CeRemoveDirectory_(unicode(path))
def rmTree(self, path):
for entry in self.listFiles(path):
if self.isFile(entry):
self.rmFile(entry)
elif self.isDir(entry):
self.rmTree(entry)
#else: # what the heck is it?
self.rmDir(path)
def listFiles(self, path, incAttrs=False):
files = self.findFiles(self.joinPath(path, '*'), incAttrs)
if incAttrs:
return [(self.joinPath(path, p[0]),) + p[1:] for p in files]
else:
return [self.joinPath(path, p) for p in files]
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._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._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._CeCreateFile_(unicode(toPath), GENERIC_WRITE, FILE_SHARE_READ, None, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)
if hceFile == 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._CeWriteFile_(hceFile, data, len(data), byref(dwWritten), None)
data = data[dwWritten.value:]
dwWritten.value = 0
data = hostFile.read(self.blockSize)
finally:
self._CeCloseHandle_(hceFile)
def getAttrs(self, path):
result = self._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.isDir(path)
self.isDir(path)
return self.exists(path)
def fileExists(self, path):
#return self.isFile(path)
self.isFile(path)
return self.exists(path)
def isDir(self, path):
attr = self.getAttrs(path)
if attr is None:
#print ('isDir:', path, attr)
return None
#print ('isDir:', path, attr, bool(attr & FILE_ATTRIBUTE_DIRECTORY))
return attr and (attr & FILE_ATTRIBUTE_DIRECTORY)
def isFile(self, path):
attr = self.getAttrs(path)
if attr is None:
#print ('isFile:', path, attr)
return None
#print ('isFile:', path, attr, not (attr & FILE_ATTRIBUTE_DIRECTORY))
return attr and not (attr & FILE_ATTRIBUTE_DIRECTORY)
def fileSize(self, path):
for each in self.findFiles(path, True):
return each[1]
return 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._CeCreateFile_(unicode(fromPath), GENERIC_READ, FILE_SHARE_READ, None, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
if hceFile == INVALID_HANDLE_VALUE:
raise OSError("Error opening the file on the device for reading")
try:
dwRead = c_ulong(1)
data = (self.blockSize * c_char)()
while dwRead.value:
dwRead.value = 0
self._CeReadFile_(hceFile, data, len(data), byref(dwRead), None)
hostFile.write(data.raw[:dwRead.value])
finally:
self._CeCloseHandle_(hceFile)
return hostFile
def openFile(self, name, mode='rU', buffering=None):
return self.CEFile(name, mode, buffering)
def popenDevice(self, path, commandLine=u''):
processInfo = PROCESS_INFORMATION()
result = bool(self._CeCreateProcess_(unicode(path), unicode(commandLine), None, None, False, 0, None, None, None, byref(processInfo)))
return result
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.
_______________________________________________
PythonCE mailing list
PythonCE@python.org
http://mail.python.org/mailman/listinfo/pythonce