We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you a podcast all about Citrix Workspace, moving to the cloud, and analytics & intelligence. Episode 2 coming soon!Listen Now


Printer WaitForSingleObject problems

nmsltd asked
Medium Priority
Last Modified: 2013-12-03
The code below is SUPPOSED to wait until the print spooler has a job submitted to it. Unfortunately, it always returns IMMEDIATELY from the WaitForSingleObject without waiting for a job! All above this point doesn't error (have stripped out error checking!
DWORD needed, returned;
HANDLE printer = 0;
BOOL didit;
PRINTER_INFO_1 printers[255];
DWORD event;
HANDLE changenotify;

EnumPrinters((DWORD)PRINTER_ENUM_NAME,(LPTSTR)"Windows 95 Local Print Provider",
pdefaults.pDatatype = NULL;
pdefaults.pDevMode = NULL;
pdefaults.DesiredAccess = PRINTER_ACCESS_ADMINISTER;
// Now let's see if we can wait for a job!
changenotify = FindFirstPrinterChangeNotification(printer,PRINTER_CHANGE_ALL,0,NULL);
event = WaitForSingleObject(changenotify,INFINITE);
MessageBox("Wait Completed","Wait");
      char buff[50];
      wsprintf(buff,"failed...%d",GetLastError()); // **HERE IS WHERE IT ALWAYS FAILS!! ** With the informative error code 6!!!
else if(event == PRINTER_CHANGE_JOB)
      MessageBox("Yippee Printer change job signalled\n","Mwuhahaha");
      sprintf(buff,"Hmmm....wait returned %d",event);
Watch Question

What is error code (returned by GetLastError) printed in follow statement?

if(event==WAIT_FAILED) { wsprintf(buff,"failed...%d",GetLastError());


Edited text of question
Error code 6 mean 'Invalid handle'
Did you check changenotyfy variable after calling FindFirstPrinterChangeNotification() to make sure it is not equal INVALID_HANDLE_VALUE? If so, invoke GetLastError() immediately after this call and check error code.

Also, is OpenPrinter() return TRUE?
I'm not sure you can set these values to NULL:
  pdefaults.pDatatype = NULL;
  pdefaults.pDevMode = NULL;

May be, better try this:

If it works, please let me know to turn comments into answer.
also make sure your linking to the multi-threaded libraries, because by default (msvc 4.x and 5.x) they are single-threaded..


In response to above comments:
Yes I do check for INVALID_HANDLE_VALUE (it's ok).
OpenPrinter does indeed return TRUE.

According to the Borland C++ V5 helpdoc on open printer:
".....or obtain a handle to a print server to call WaitForPrinterChange. To do so, it should call OpenPrinter with pPrinterName set to the name of the server and should specify a server access mask value such as SERVER_ALL_ACCESS. The pDatatype and pDevMode members of the PRINTER_DEFAULTS data structure should be set to NULL. The handle returned by such a call may be passed to the ClosePrinter or WaitForPrinterChange function.

So (allegedly) you can set these values to NULL.

I am linking multithreading libraries.

I have tried OpenPrinter(printers[0].pName,(LPHANDLE)&printer,NULL);
Still doesn't work! :(

My only thoughts on the matter reading the above snippet from the helpdoc is that it says "print server". Is there a difference between a printer returned from EnumPrinters and a print server, or a print provider? I have found no real explanation of the terminology in any documentation (oh for a decent book on windows printer programming - are there any???)
Hope this clarifies the problem!
http://www.microsoft.com/win32dev/guidelns/apidiffs.htm DECLARES:

Printer change notification

Printer change notification print spooler functions are not supported on Windows 95 nor on Windows 95 OSR 2. The following functions are not supported:




You cannot use FindFirstPrinterChange... in Windows95 (see comments above). This function just does nothing and returns 0 (not INVALID_HANDLE_VALUE!!!).

That is output of my little test program (code see below):

*** EnumPrinters() 1 0 Needed:396 Returned: 5
pDesc: HP LaserJet 4P,HP LaserJet 4P,
pName: HP LaserJet 4P
*** OpenPrinter() 1 0 Handle:0x005105a8
*** ChangeNotify() 1 78 Handle:0x00000000
*** WaitForSingleObject() 0 6 Handle:ffffffff

// Here is test program

#include <iostream.h>
#include <windows.h>

// Compile as BCC32 -WM <filename>
void main(int argc,char* argv[])
   if(argc<2) return;

   BOOL r;
   DWORD needed, returned;
   PRINTER_INFO_1 printers[255];
   cout<<"*** EnumPrinters() ";
   cout<<r<<' '<<GetLastError()<<" Needed:"<<needed<<" Returned: "<<returned<<endl;
   if(!r) return;
   cout<<"pDesc: "<<printers[0].pDescription<<endl<<"pName: "<<printers[0].pName<<endl<<
      "pComment: "<<printers[0].pComment<<endl;

   HANDLE printer = 0;
   PRINTER_DEFAULTS pdefaults;
   pdefaults.pDatatype = NULL;
   pdefaults.pDevMode = NULL;
   pdefaults.DesiredAccess = PRINTER_ACCESS_ADMINISTER;
   cout<<"*** OpenPrinter() ";
   cout<<r<<' '<<GetLastError()<<" Handle:"<<hex<<printer<<endl;
   if(!r) return;

   cout<<"*** ChangeNotify() ";
   HANDLE changenotify=FindFirstPrinterChangeNotification(printer,PRINTER_CHANGE_ALL,0,NULL);
   cout<<(changenotify!=INVALID_HANDLE_VALUE)<<' '<<GetLastError()<<" Handle:"<<hex<<
   if(changenotify==INVALID_HANDLE_VALUE) return;

   cout<<"*** WaitForSingleObject() ";
   DWORD event=WaitForSingleObject(changenotify,INFINITE);
   cout<<(event!=WAIT_FAILED)<<' '<<GetLastError()<<" Handle:"<<hex<<event<<endl;
   if(event==WAIT_FAILED) return;

   cout<<"Wait success: "<<event<<endl;

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts
FindFirstPrinterChangeNotification() works fine for NT, but not for Windows95!


100% Correct! I discovered this myself at 1:30 this afternoon!
Great minds think alike, eh Nick?! Now all I have to figure out is how I'm going to implement FindFirstPrinterChangeNotification on win95 & the project's home and dry :)
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.


Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.