home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_2499 < prev    next >
Encoding:
Text File  |  2003-03-12  |  5.3 KB  |  156 lines

  1. # A Demo of services and named pipes.
  2.  
  3. # A multi-threaded service that simply echos back its input.
  4.  
  5. # * Install as a service using "pipeTestService.py install"
  6. # * Use Control Panel to change the user name of the service
  7. #   to a real user name (ie, NOT the SystemAccount)
  8. # * Start the service.
  9. # * Run the "pipeTestServiceClient.py" program as the client pipe side.
  10.  
  11. import win32serviceutil, win32service
  12. import pywintypes, win32con, winerror
  13. # Use "import *" to keep this looking as much as a "normal" service
  14. # as possible.  Real code shouldn't do this.
  15. from win32event import *
  16. from win32file import *
  17. from win32pipe import *
  18. from win32api import *
  19. from ntsecuritycon import *
  20.  
  21. import traceback
  22. import thread
  23.  
  24. def ApplyIgnoreError(fn, args):
  25.     try:
  26.         return apply(fn, args)
  27.     except error: # Ignore win32api errors.
  28.         return None
  29.  
  30. class TestPipeService(win32serviceutil.ServiceFramework):
  31.     _svc_name_ = "PyPipeTestService"
  32.     _svc_display_name_ = "Python Pipe Test Service"
  33.     def __init__(self, args):
  34.         win32serviceutil.ServiceFramework.__init__(self, args)
  35.         self.hWaitStop = CreateEvent(None, 0, 0, None)
  36.         self.overlapped = pywintypes.OVERLAPPED()
  37.         self.overlapped.hEvent = CreateEvent(None,0,0,None)
  38.         self.thread_handles = []
  39.  
  40.     def CreatePipeSecurityObject(self):
  41.         # Create a security object giving World read/write access,
  42.         # but only "Owner" modify access.
  43.         sa = pywintypes.SECURITY_ATTRIBUTES()
  44.         sidEveryone = pywintypes.SID()
  45.         sidEveryone.Initialize(SECURITY_WORLD_SID_AUTHORITY,1)
  46.         sidEveryone.SetSubAuthority(0, SECURITY_WORLD_RID)
  47.         sidCreator = pywintypes.SID()
  48.         sidCreator.Initialize(SECURITY_CREATOR_SID_AUTHORITY,1)
  49.         sidCreator.SetSubAuthority(0, SECURITY_CREATOR_OWNER_RID)
  50.  
  51.         acl = pywintypes.ACL()
  52.         acl.AddAccessAllowedAce(FILE_GENERIC_READ|FILE_GENERIC_WRITE, sidEveryone)
  53.         acl.AddAccessAllowedAce(FILE_ALL_ACCESS, sidCreator)
  54.  
  55.         sa.SetSecurityDescriptorDacl(1, acl, 0)
  56.         return sa
  57.  
  58.     # The functions executed in their own thread to process a client request.
  59.     def DoProcessClient(self, pipeHandle, tid):
  60.         try:
  61.             try:
  62.                 # Create a loop, reading large data.  If we knew the data stream was
  63.                 # was small, a simple ReadFile would do.
  64.                 d = ''
  65.                 hr = winerror.ERROR_MORE_DATA
  66.                 while hr==winerror.ERROR_MORE_DATA:
  67.                     hr, thisd = ReadFile(pipeHandle, 256)
  68.                     d = d + thisd
  69.                 print "Read", d
  70.                 ok = 1
  71.             except error:
  72.                 # Client disconnection - do nothing
  73.                 ok = 0
  74.  
  75.             # A secure service would handle (and ignore!) errors writing to the 
  76.             # pipe, but for the sake of this demo we dont (if only to see what errors
  77.             # we can get when our clients break at strange times :-)
  78.             if ok: WriteFile(pipeHandle,"%s (on thread %d) sent me %s" % (GetNamedPipeHandleState(pipeHandle)[4],tid, d))
  79.         finally:
  80.             ApplyIgnoreError( DisconnectNamedPipe, (pipeHandle,) )
  81.             ApplyIgnoreError( CloseHandle, (pipeHandle,) )
  82.  
  83.     def ProcessClient(self, pipeHandle):
  84.         try:
  85.             procHandle = GetCurrentProcess()
  86.             th = DuplicateHandle(procHandle, GetCurrentThread(), procHandle, 0, 0, win32con.DUPLICATE_SAME_ACCESS)
  87.             try:
  88.                 self.thread_handles.append(th)
  89.                 try:
  90.                     return self.DoProcessClient(pipeHandle, th)
  91.                 except:
  92.                         traceback.print_exc()
  93.             finally:
  94.                 self.thread_handles.remove(th)
  95.         except:
  96.             traceback.print_exc()
  97.  
  98.     def SvcStop(self):
  99.         self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
  100.         SetEvent(self.hWaitStop)
  101.  
  102.     def SvcDoRun(self):
  103.         # Write an event log record - in debug mode we will also 
  104.         # see this message printed.
  105.         import servicemanager
  106.         servicemanager.LogMsg(
  107.             servicemanager.EVENTLOG_INFORMATION_TYPE,
  108.             servicemanager.PYS_SERVICE_STARTED,
  109.             (self._svc_name_, '')
  110.             )
  111.             
  112.         num_connections = 0
  113.         while 1:
  114.             pipeHandle = CreateNamedPipe("\\\\.\\pipe\\PyPipeTest",
  115.                 PIPE_ACCESS_DUPLEX| FILE_FLAG_OVERLAPPED,
  116.                 PIPE_TYPE_MESSAGE | PIPE_READMODE_BYTE,
  117.                 PIPE_UNLIMITED_INSTANCES,    # max instances
  118.                 0, 0, 6000,
  119.                 self.CreatePipeSecurityObject())
  120.             try:
  121.                 hr = ConnectNamedPipe(pipeHandle, self.overlapped)
  122.             except error, details:
  123.                 print "Error connecting pipe!", details
  124.                 CloseHandle(pipeHandle)
  125.                 break
  126.             if hr==winerror.ERROR_PIPE_CONNECTED:
  127.                 # Client is already connected - signal event
  128.                 SetEvent(self.overlapped.hEvent)
  129.             rc = WaitForMultipleObjects((self.hWaitStop, self.overlapped.hEvent), 0, INFINITE)
  130.             if rc==WAIT_OBJECT_0:
  131.                 # Stop event
  132.                 break
  133.             else:
  134.                 # Pipe event - spawn thread to deal with it.
  135.                 thread.start_new_thread(self.ProcessClient, (pipeHandle,))
  136.                 num_connections = num_connections + 1
  137.  
  138.         # Sleep to ensure that any new threads are in the list, and then
  139.         # wait for all current threads to finish.
  140.         # What is a better way?
  141.         Sleep(500)
  142.         while self.thread_handles:
  143.             self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING, 5000)
  144.             print "Waiting for %d threads to finish..." % (len(self.thread_handles))
  145.             WaitForMultipleObjects(self.thread_handles, 1, 3000)
  146.         # Write another event log record.
  147.         servicemanager.LogMsg(
  148.             servicemanager.EVENTLOG_INFORMATION_TYPE,
  149.             servicemanager.PYS_SERVICE_STOPPED,
  150.             (self._svc_name_, " after processing %d connections" % (num_connections,))
  151.             )
  152.  
  153.  
  154. if __name__=='__main__':
  155.     win32serviceutil.HandleCommandLine(TestPipeService)
  156.