Notes on DynaMon: Starts w/ DisableThreadCalls InitializePrintMonitor: Simply a Port MOn Fill out MonitorEx Build CritSecs EnumPorts: Get the EnumIndex Load SetupAPI stuff Enter CritSec If we haven't completed a previous Enum do another one WalkPortList else keep track of skipped enums Build the List to return Check Level & Figure Size If big enough buffer build each port info struct Give the new list to the Background Thread (PassPortUpdateListToBT) Leave CritSec Unload SetupAPI UpdateNumber of Enumports WalkPortList: Re-Enter CtitSec Return Security to System Get a list of USB Printers (And Dot4 & SCSIPrnt & Parallel) Go through the list one at a time Get the device deatil See if the port is active If inactive & already in list skip it If active & status is the same skip it Process the port (ProcessPortInfo) Loop Exit the CritSec Destroy the DevList Impersonate the Client ProcessPortInfo: First Get the PortName & Open the DevNode (GetPortNameAndRegKey) If we can't find a RegKey or Port Number Add to list as Useless Entry & return (AddUselessPortEntry) Find Port in the List (FindPort) If it is in list & it changed Update it's info (UpdatePortInfo) If not in list Add it (AddPortToList) GetPortNameAndRegKey: Try to Open Device Intf. RegKey If fails return invalid handle Now get the port NUmber from the Reg If this fails return Invalid Handle Get Base Name from Reg Buld the Port Name Return hRegKey & PortName AddUselessPortEntry: See if the port is already in the Useless List (FindUselessPortEntry) If found don't add it Create a useless Port Entry & insert it in the list FindPort: Enter CritSec Search list looking for portname match Stop if name matches or is greater If no match return NULL. Still return pointer to previous space in list Exit CritSec UpdatePortInfo: Get new DevicePath & Port Description If DEviceFlags ahve changed Store new Flags Add this to UpdateList (AddToPortUpdateList) AddPortToList: Alloc Mem for new PortInfo Copy in all pertinent info Add to the good port list Check if this is also in the Useless port list (FindUselessEntry) If in USeless List fix pointers, free mem, & dec count Add to Update list Inc port count FindUselessPortEntry: Search UselessList for matching portname If found return pointer to current & previous entries. AddToPortUpdateList: Create an UPDATE_INFO & fill in Add new info to front of the list PassPortUpdateListToBT: Check if any update threads currently NO: Create a new thread and give it the list One: Create a backup thread and give it new list Two: Add these update port to the list of 2nd thread CreateBTAndReturnEvent: Create a new event Create a new occurance of BackgroundThread BackgroundThread: Wait for Trigger Get Update List & CritSec Get list fo all local printers Process the update list Check if portname is used by spooler OpenPort: Find the port in our List (FindPort) If Found Init CritSEc & Return Handle ClosePort: Delete CritSec StarDocPort: Open the Printer (OpenPrinter) Save JobId Actually open the device port (LocalOpenPort) If it fails CLose the printer else Set StartDoc Flag LocalOpenPort: Enter Port CritSec If Handle is Invalid If we have a ref count exit Open a handle to the device If this fails with FILE_NOT_FOUND Try to rebuild the stack for Dot4 (DOT4PNP) If success create an event for Overlapped I/O Bump Ref Count Leave Port Critsec Dot4PnP: Make sure it is a Dot4 device Load Config Manager DLL Revert to System Force PnP on parallel port Impersonte User Try to open the device again Free CM DLL EndDocPort: If all data has not been sent If job should aborted (AbortThisJob) If data is currently scheduled Cancel the write Get the write status Not Abort but still data scheduled get status of last right else wait a sec reschedule current write If job shoudl be restarted (NeedToResubmitJob) Invalidate Port (InvalidatePortHandle) Set job control to restart exit loop Until all data sent Free up the data buffers (FreeWriteBuffer) Turn off StartDoc flag Close the port handle (LocalClosePort) show all data sent Close the printer AbortThisJob: Get current Job Info If status is bad (Deleting,Deleted,Restart) return TRUE NeedToResubmitJob: Compare Error passed in with list of failure codes... If match return TRUE InvalidatePortHandle: Close the Device & Overlap Event Reset Pointers Free data (FreeWRiteBuffer) FreeWriteBuffer: Free memory & reset size args LocalClosePort: Enter Port Critsec Dec Ref Count If still open end (cRef > 0) Close Device & Event Exit Critsec WritePort: Set write timeout For USB tweak Buffersize down to 4K If device closed restart Job Fail call w/ Cancelled Try to Open Port (LocalOpenPort) If failed return while still old data to be sent If already scheduled check status (GetTimeLeft) (ScheduleWriteStatus else Schedule it (ScheduleWrite) Any errors Fail out If we have too much data for our current buffer Free current (FreeWriteBuffer) Allocate a new one... Copy the Data to our buffer while still new data to be sent If already scheduled check status (GetTimeLeft) (ScheduleWriteStatus else Schedule it (ScheduleWrite) Any errors Fail out If this is a write outside a StartDoc (LM write) Don't let any writes carry over (CancelIO) Get the status of write (ScheduledWriteStatus) Set amount writtne & free buffer If some data was written or scheduled tell spooler all was writtne else free the buffer Done: Check if job needs to be restarted (NeedToResubmitJob) If so invalidate the port else if we failed due to timeout Get the port status (GetLptStatus) Close theport (LocalClosePort) ScheduleWrite: Shouldn't be any data scheduled or not completed Schedule any data not sent Call Write of schduleded data (WriteFile) If write failed If LastError is success set to unknown else if IO_PENDING set to success If LastError not Success Show that no data was scheduled Return LastError GetTimeLeft: If the current timeout is the MAX reutn the MAX Get current Time Compare if Timeout ha expired If yes then return 0 Else return how much time left until timeout expires. ScheduledWriteStatus: Wait for Overlapped Event to signal If timed out Return Timeout error Get Result Reset the Overlap Event Update the amount completed by the amount written Clear amount scheduled since no write pending return LastError GetLPTStatus: Create Overlap Event Send a USBPRINT IOCTL to get the parallel status If status returned set the status byte else set a benign status Close the Event SetPortTimeouts: Save data in TO struct ReadPort: Create a new Read Handle & Overlap struct Do a ReadFile on Handle Wait for OVerlap Event If Event Timed Out Cancel Read Get Result If failure return no data read Close Event & Read Handle GetPrinterDataFomrPort: If not ControlID fail Create Overlap Event Open the Port (LocalOpenPort) If IOCTL = QUERY_DEVICE_ID