1

Resolved

Issue with PrintWatchQueue on 64 bit systems

description

Hello!
 
I have been trying to use the PrintWatchQueue component, but I have been running into an odd issue... When adding any printer using the .AddPrinter method I receive the following error:
 
Attempted to read or write protected memory. this is often an indication that other memory is corrupt.
 
I was using the latest version of the component (2.0.7.0) on a WindowsXP 64 box, Visual Studio 2005. When I tried to open the source code, I discovered it was written in VS 2008. Thinking that it might be a problem with the target CPU, I loaded the source code in a Server 2008 (32 bit)/VS 2008 virtual machine that I have. I checked - the target CPU was set to "Any CPU", so that wasn't the problem...
 
I recompiled anyhow, and copied the new dll back to my application on the 64 bit machine. Ran the program - encountered the same error. I then switched gears, and moved my app to the virtual machine. Converted the project to VS2008, compiled and ran it - BINGO! No error! Interesting - is this a 32 bit vs. 64 bit Framework issue? On to further investigation...
 
I needed to debug your source code to identify the location of the error, but the only source I had was VS 2008. So, I dug around a bit on MerrionComputing.com and on the CodePlex PUMA site. I found that the PrintQueueWatch code in the PUMA source was VS 2005. I recompiled the code, replaced the dll in my app, and was able to establish debugging. Here is what I found:
 
When I call the .AddPrinter method, the code executes successfully through creating a New PrinterInformation class when the DesiredAccess is set to 131080, but when it tries to create the class with DesiredAccess set to PrinterAccessRights.PRINTER_ALL_ACCESS (983052) the code throws theprotected memory error.
 
So there is the source of the error, but my knowledge of the Printer world is much too limited for me to make any sense of it. Do you have any ideas?
 
Thanks,
 
Eric

comments

lgahan wrote Feb 17, 2011 at 11:58 PM

Hi,

I have recently been working on a project that requires the use of the PrintQueueWatch component in a 64-bit process running on Windows Server 2008 R2. Our use of the component is fairly modest, but we have been able to get the functionality we are interested in (print job notifications) working on 64-bit by making the following changes to the 2.0.7.2 source code:

1 - Replace Int32 with IntPtr when referencing native pointer types

We replaced uses of Int32 with IntPtr when referencing native pointer types in the SpoolerApi.vb P/Invoke declarations and SpoolerStructs.vb structure fields. Further modifications were required throughout the code where IntPtrs were cast to 32-bit integers for the purposes of comparison or pointer arithmetic - Helper methods were added to MCLApiUtilities to facilitate the operations on both 32- and 64-bit.

After making these changes, the code appeared to run successfully but none of the PrintJob events (Added, Set, Written, Deleted) were being raised, which led us to the next problem.

2 - Modify PrinterNotifyInfoData structure to lay out correctly in 64-bit memory

The issue is explained in detail here: http://lifeandtimesofadeveloper.blogspot.com/2007_10_01_archive.html but, in a nutshell, the PRINTER_NOTIFY_INFO and PRINTER_NOTIFY_INFO_DATA structures are laid out differently in 64-bit memory space than 32-bit.

As a result, these structures were not getting marshaled correctly between managed and unmanaged memory and the printer notification data could not be interpretted by the PrinterChangeNotificationThread.

We made the changes to the PrinterNotifyInfo and PrinterNotifyInfoData classes that were described in the aforementioned blog post and the JobAdded, JobSet and JobDeleted events were raised thereafter. JobWritten, however, was still not being raised (which was unfortunate as that was the only event we were interested in).

3 - Raise JobWritten event based on PrintJob status

Upon investigating, we found that the PRINTER_CHANGE_WRITE_JOB flag was not set in the mpdChangeFlags returned by FindNextPrinterChangeNotification (even if we explicitly set PRINTER_CHANGE_WRITE_JOB as the watch flag in the call to FindFirstPrinterChangeNotification). This behaviour persisted even when the PrintQueueWatch component was run in a 32-bit process on Windows 2008; so the issue appears to be Windows 7/2008-related rather than a 64-bit compatibility issue.

We eventually resorted to using a hack to get around this by modifying the PrinterChangeNotificationThread to raise the JobWritten event when the PrintJob.Printed property is True. This works but we still don't understand why the PRINTER_CHANGE_WRITE_JOB flag is not being set by the Spooler API.

Hope this is of some help. I can upload the updated source code if it is of interest.

ademiritumbiara wrote Apr 4, 2011 at 12:21 PM

If you can upload the changed code, I would be very grateful. I'm working on this issue for a long time, but with no success. Thanks a lot.

Waxolunist wrote Aug 19, 2011 at 2:06 PM

Hello Igahan

I think I got the same problems. No events is being raised. Could you please somehow make the code available?

Thx, a lot

/Kind regards
Christian

Waxolunist wrote Aug 19, 2011 at 2:07 PM

Hello Igahan

I seem to have the same proble. No event is being raised.
Could you please upload your code or the changes?

Thx a lot.

/Kind regards

Christian

alexlbl wrote Sep 15, 2011 at 8:48 PM

Hello Igahan,

I'm facing the same problem trying to use the API on an x64 environment but couldn't. I'm trying to follow your instructions on converting the API to a x64 code but haven't been very succesful. Would you be kind enough to upload your source code with the changes you made to it? There must be something else I'm missing...

Thank you!

Waxolunist wrote Sep 15, 2011 at 9:33 PM

Hello alexlbl

I am running the code on a 64bit machine now. I compiled it explicitly for x86 cpu instead of any cpu and it works for me on win2008r2.
The problem is that it expects the winspool.drv as 32bit but the code resolves this file to syswow64.

Hope this helps

Kind regards
Christian

PS: @Igahan, pls in the name of opensource.

wrote Apr 15, 2012 at 9:34 PM

wrote Feb 14, 2013 at 6:55 PM

wrote May 16, 2013 at 8:34 AM

wrote May 16, 2013 at 8:34 AM

wrote Jun 14, 2013 at 7:03 AM

vasu_i wrote Sep 13, 2013 at 6:20 PM

I guess this is a dead thread and the updated code didnt make it here.