4 Replies - 1535 Views - Last Post: 24 February 2011 - 04:37 PM Rate Topic: -----

#1 HarbingTarbl  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 9
  • Joined: 10-February 11

Win32, FindNextPrinterChangeNotification always throws INVALID_HANDLE

Posted 24 February 2011 - 01:10 PM

I'm trying to use Win32 API to monitor a local printer on my machine, I have everything working... except the actual call that returns information about the print job (FindNextPrinterChangeNotification), no matter what I do or try it always fails and GetLastError() returns INVALID_HANDLE.

It had also been returning INVALID_PARAMETER for while, until I made sure to clear the PRINTER_NOTIFY_OPTIONS structure (The MSDN lies, FindNextPrinterChangeNotification does NOT ignore everything but the Flags field.

Here is my code
#include <Windows.h>
#include <stdio.h>
#include <conio.h>


int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmdLine, int nCmdShow)
{
	if(!AllocConsole()) return 1;
	if(!(freopen("CONIN$", "rb", stdin) && freopen("CONOUT$", "wb", stdout) && freopen("Errlog.log", "wb", stderr))) return 2;
	fprintf(stderr, "DEBUG : CONSOLE OK!\n");
	LPBYTE buffer = NULL;
	DWORD bufferSize = sizeof(buffer)/sizeof(buffer[0]);
	DWORD numberPrinters = 0;
	PRINTER_DEFAULTS printerPermissions;
	memset(&printerPermissions, 0, sizeof(printerPermissions));
	printerPermissions.DesiredAccess = PRINTER_ALL_ACCESS;

	//Start Printer Enum
	printf("Select the target printer\n");
	if(!EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, buffer, bufferSize, &bufferSize, &numberPrinters))
	{
		buffer = new BYTE[bufferSize];
		if(!EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, buffer, bufferSize, &bufferSize, &numberPrinters))
		{
			fprintf(stderr, "FAIL : Unable to Get Printers\n");
			delete [] buffer;
			return 3;
		}
	}
	//End Printer Enum

	//Start UI
	fprintf(stderr, "DEBUG : PRINTER LIST OK\n");
	for(unsigned int i = 0; i < numberPrinters; i++)
	{
		printf("%d : %s\n", i, (reinterpret_cast<PRINTER_INFO_4*>(buffer)+i)->pPrinterName);
	}

	fprintf(stderr, "DEBUG : LISTED PRINTERS OK!\n");
	unsigned int input = 0;
	do
	{
		scanf("%i", &input);
	}while(input >= numberPrinters);
	fprintf(stderr, "DEBUG : USER INPUT OK!\n");

	char currentPrinter[64];
	strcpy_s(currentPrinter, sizeof(currentPrinter)/sizeof(currentPrinter[0]), (reinterpret_cast<PRINTER_INFO_4*>(buffer)+input)->pPrinterName);
	delete [] buffer;
	bufferSize = 0;
	HANDLE selectedPrinter = NULL;
	//End UI

	//HACK FIX LATER
	OpenPrinter(currentPrinter, &selectedPrinter, NULL);
	if(!GetPrinter(selectedPrinter, 2, buffer, bufferSize, &bufferSize))
	{
		buffer = new BYTE[bufferSize];
		GetPrinter(selectedPrinter, 2, buffer, bufferSize, &bufferSize);
		printerPermissions.pDatatype = reinterpret_cast<PRINTER_INFO_2*>(buffer)->pDatatype;
		printerPermissions.pDevMode = reinterpret_cast<PRINTER_INFO_2*>(buffer)->pDevMode;
		ClosePrinter(selectedPrinter);
	}
	//END HACK

	//Start Open Printer
	if(!OpenPrinter(currentPrinter, &selectedPrinter, &printerPermissions))
	{
		fprintf(stderr, "FAIL : Unable to open %s\n", currentPrinter);
		return 4;
	}
	delete [] buffer;
	fprintf(stderr, "DEBUG : PRINTER OPEN OK!\n");
	//End Open Printer
	//Start Hook Printer
	fprintf(stderr, "DEBUG : HOOKING PRINTER....\n");
	HANDLE printerHook = NULL;
	if((printerHook = FindFirstPrinterChangeNotification(selectedPrinter, PRINTER_CHANGE_ADD_JOB, 0, NULL)) == NULL)
	{
		fprintf(stderr, "FAIL : Unable to hook printer\n");
		ClosePrinter(selectedPrinter);
		return 5;
	}
	fprintf(stderr, "DEBUG : PRINTER HOOK OK!\n");
	//End Hook Printer

	//Start Wait
	fprintf(stderr, "DEBUG : STARTING WAIT.....\n");
	switch(WaitForSingleObject(printerHook, 20000))
	{
	case WAIT_ABANDONED:
		fprintf(stderr, "FAIL : Wait Failed - Abandonded\n");
		FindClosePrinterChangeNotification(printerHook);
		ClosePrinter(selectedPrinter);
		return 6;
	case WAIT_FAILED:
		fprintf(stderr, "FAIL : Wait Failed - Error Code %i\n", GetLastError());
		FindClosePrinterChangeNotification(printerHook);
		ClosePrinter(selectedPrinter);
		return 7;
		break;
	case WAIT_TIMEOUT:
		fprintf(stderr, "FAIL : Wait Failed - Wait Timeout\n");
		FindClosePrinterChangeNotification(printerHook);
		ClosePrinter(selectedPrinter);
		return 8;
	}
	fprintf(stderr, "DEBUG : WAIT OK!\n");
	//End Wait

	//Start Notify
	PRINTER_NOTIFY_OPTIONS notifyOptions;
	PRINTER_NOTIFY_INFO* notifyInfo = NULL;
	memset(&notifyOptions, 0, sizeof(notifyOptions));
	notifyOptions.Flags = PRINTER_NOTIFY_OPTIONS_REFRESH;
	notifyOptions.Version = 2;
	if(!FindNextPrinterChangeNotification(printerHook, NULL, &notifyOptions, reinterpret_cast<LPVOID*>(&notifyInfo))) //Problem is here
	{
		fprintf(stderr, "FAIL : Unable to get Notification Info - Error Code %i\n", GetLastError());

		FindClosePrinterChangeNotification(printerHook);
		ClosePrinter(selectedPrinter);
		return 9;
	}

	for(int i = 0; i < notifyInfo->Count; i++)
	{
		if(notifyInfo->aData[i].Type == JOB_NOTIFY_TYPE && notifyInfo->aData[i].Field == JOB_NOTIFY_FIELD_DOCUMENT)
		{
			printf("DOCUMENT : %s\n", notifyInfo->aData[i].NotifyData.Data.pBuf);
		}
	}
	fprintf(stderr, "DEBUG : NOTIFYINFO OK!");
	//End Notify

	FreePrinterNotifyInfo(notifyInfo);
	FindClosePrinterChangeNotification(printerHook);
	ClosePrinter(selectedPrinter);
	getch();
	fprintf(stderr, "DEBUG : PROGRAM EXIT OK!");
	return 0;
}




Any help at all would be appreciated, I have been banging my head against this for the past 2 hours without any progress, even the Great Google has not been much help.

And before you ask, Yes I have both UAC and the windows firewall turned off and I know I shouldn't be using ASCII, but I didn't want to bother with Unicode until I at least got the printing stuff working.

Is This A Good Question/Topic? 0
  • +

Replies To: Win32, FindNextPrinterChangeNotification always throws INVALID_HANDLE

#2 JackOfAllTrades  Icon User is offline

  • Saucy!
  • member icon

Reputation: 5954
  • View blog
  • Posts: 23,224
  • Joined: 23-August 08

Re: Win32, FindNextPrinterChangeNotification always throws INVALID_HANDLE

Posted 24 February 2011 - 01:57 PM

Have you stepped through the code in the debugger?
Was This Post Helpful? 0
  • +
  • -

#3 HarbingTarbl  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 9
  • Joined: 10-February 11

Re: Win32, FindNextPrinterChangeNotification always throws INVALID_HANDLE

Posted 24 February 2011 - 02:35 PM

Yes, well, at least as much of the code as I can as I cannot step into the actual function itself.

I have made some progress however, it seems that the error was caused by setting the Flag field of the PRINTER_NOTIFY_OPTIONS structure. I have cleared the Flag and am now packing the data into the PRINTER_NOTIFY_OPTIONS_TYPE and PRINTER_INFO_DATA structures by hand.

It seems to be working... mostly. For some reason it's returning the incorrect fields. Not completely sure why. The code I am using to populate the fields is:
PRINTER_NOTIFY_OPTIONS notifyOptions;
	PRINTER_NOTIFY_OPTIONS_TYPE notifyTypes[1];
	PRINTER_NOTIFY_INFO_DATA notifyData[1];
	ZeroMemory(&notifyData, sizeof(notifyData));
	ZeroMemory(&notifyTypes, sizeof(notifyTypes));
	notifyData[0].Type = JOB_NOTIFY_TYPE;
	notifyData[0].Field = JOB_NOTIFY_FIELD_DOCUMENT;
	notifyTypes[0].Count = 1;
	notifyTypes[0].Type = JOB_NOTIFY_TYPE;
	notifyTypes[0].pFields = reinterpret_cast<PWORD>(notifyData);
	ZeroMemory(&notifyOptions, sizeof(notifyOptions));
	notifyOptions.Version = 2;
	notifyOptions.Count = 1;
	notifyOptions.pTypes = notifyTypes;



It is returning the name of the computer that sent the document instead of the actual document name, but it's still progress.
Was This Post Helpful? 0
  • +
  • -

#4 JackOfAllTrades  Icon User is offline

  • Saucy!
  • member icon

Reputation: 5954
  • View blog
  • Posts: 23,224
  • Joined: 23-August 08

Re: Win32, FindNextPrinterChangeNotification always throws INVALID_HANDLE

Posted 24 February 2011 - 04:00 PM

Sorry, I'm not much help here. I work with the Win32 API very little, and never in the Printer space.

EDIT: I note that reading the docs for PRINTER_NOTIFY_INFO_DATA struct this:

Quote

Id

Indicates the job identifier if the Type member specifies JOB_NOTIFY_TYPE. If the Type member specifies PRINTER_NOTIFY_TYPE, this member is undefined.


You are in fact specifying a Type of JOB_NOTIFY_TYPE, but you're not sending an Id. No idea if that's relevant or not.

This post has been edited by JackOfAllTrades: 24 February 2011 - 04:02 PM

Was This Post Helpful? 0
  • +
  • -

#5 HarbingTarbl  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 9
  • Joined: 10-February 11

Re: Win32, FindNextPrinterChangeNotification always throws INVALID_HANDLE

Posted 24 February 2011 - 04:37 PM

Well, I'm not sure myself to be honest. I think the purpose of these structs is a little like the "hint" structs used in socket programming. But that's just me guessing.

As for specifying the Job ID... I'm not sure if it needs to be set or not. These structs are what the actual data is passed back in, so there are certain fields that the function is supposed to fill out for me. Not sure which fields I am supposed to fill out and which I should leave blank though.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1