Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Select Printer Programmatically Problem

Posted on 2006-11-10
6
Medium Priority
?
845 Views
Last Modified: 2013-11-20
Hello.

I would like to programtically change the printer i print to.  The way i was going to do this was simple by changing the default printer for the application before calling the print operation.  Eventually i want to allow my users to do this through automation but i am just testing it out now.  After reading stuff on the internet and here i decided that this was the best implementation.

http://support.microsoft.com/kb/166129

the code for it is below.  I Get a problem at this point towards the bottom;
"// set the new hDevMode and hDevNames
    *phDevMode = hDevMode;
    *phDevNames = hDevNames;
    return TRUE;
"
The error message returned is "Unhandled exception at 0x0040f714 in MyApp.exe: 0xC0000005: Access violation writing location 0x0040515c."

I have no idea why it is doing this please help.

BOOL MyApp::ChangePrinter()
{
      BOOL ret = TRUE;
      LPTSTR str = _T("Acrobat Distiller");
      ret = GetPrinterDevice(str,&m_hDevNames,&m_hDevMode);
 }

BOOL MyApp::GetPrinterDevice(LPTSTR pszPrinterName, HGLOBAL* phDevNames, HGLOBAL* phDevMode)
{
    // if NULL is passed, then assume we are setting app object's
    // devmode and devnames
    if (phDevMode == NULL || phDevNames == NULL)
        return FALSE;

    // Open printer
    HANDLE hPrinter;
    if (OpenPrinter(pszPrinterName, &hPrinter, NULL) == FALSE)
        return FALSE;

    // obtain PRINTER_INFO_2 structure and close printer
    DWORD dwBytesReturned, dwBytesNeeded;
    GetPrinter(hPrinter, 2, NULL, 0, &dwBytesNeeded);
    PRINTER_INFO_2* p2 = (PRINTER_INFO_2*)GlobalAlloc(GPTR,
        dwBytesNeeded);
    if (GetPrinter(hPrinter, 2, (LPBYTE)p2, dwBytesNeeded,
       &dwBytesReturned) == 0) {
       GlobalFree(p2);
       ClosePrinter(hPrinter);
       return FALSE;
    }
    ClosePrinter(hPrinter);

    // Allocate a global handle for DEVMODE
    HGLOBAL  hDevMode = GlobalAlloc(GHND, sizeof(*p2->pDevMode) +
       p2->pDevMode->dmDriverExtra);
    ASSERT(hDevMode);
    DEVMODE* pDevMode = (DEVMODE*)GlobalLock(hDevMode);
    ASSERT(pDevMode);

    // copy DEVMODE data from PRINTER_INFO_2::pDevMode
    memcpy(pDevMode, p2->pDevMode, sizeof(*p2->pDevMode) +
       p2->pDevMode->dmDriverExtra);
    GlobalUnlock(hDevMode);

    // Compute size of DEVNAMES structure from PRINTER_INFO_2's data
    DWORD drvNameLen = lstrlen(p2->pDriverName)+1;  // driver name
    DWORD ptrNameLen = lstrlen(p2->pPrinterName)+1; // printer name
    DWORD porNameLen = lstrlen(p2->pPortName)+1;    // port name

    // Allocate a global handle big enough to hold DEVNAMES.
    HGLOBAL hDevNames = GlobalAlloc(GHND,
        sizeof(DEVNAMES) +
        (drvNameLen + ptrNameLen + porNameLen)*sizeof(TCHAR));
    ASSERT(hDevNames);
    DEVNAMES* pDevNames = (DEVNAMES*)GlobalLock(hDevNames);
    ASSERT(pDevNames);

    // Copy the DEVNAMES information from PRINTER_INFO_2
    // tcOffset = TCHAR Offset into structure
    int tcOffset = sizeof(DEVNAMES)/sizeof(TCHAR);
    ASSERT(sizeof(DEVNAMES) == tcOffset*sizeof(TCHAR));

    pDevNames->wDriverOffset = tcOffset;
    memcpy((LPTSTR)pDevNames + tcOffset, p2->pDriverName,
        drvNameLen*sizeof(TCHAR));
    tcOffset += drvNameLen;

    pDevNames->wDeviceOffset = tcOffset;
    memcpy((LPTSTR)pDevNames + tcOffset, p2->pPrinterName,
        ptrNameLen*sizeof(TCHAR));
    tcOffset += ptrNameLen;

    pDevNames->wOutputOffset = tcOffset;
    memcpy((LPTSTR)pDevNames + tcOffset, p2->pPortName,
        porNameLen*sizeof(TCHAR));
    pDevNames->wDefault = 0;

    GlobalUnlock(hDevNames);
    GlobalFree(p2);   // free PRINTER_INFO_2

    // set the new hDevMode and hDevNames
   //problem happens on these next two lines of code
    *phDevMode = hDevMode;
    *phDevNames = hDevNames;
    return TRUE;
}
0
Comment
Question by:wdhough
  • 3
  • 2
6 Comments
 
LVL 22

Accepted Solution

by:
mahesh1402 earned 1500 total points
ID: 17916053
How you are passing parameters to  GetPrinterDevice() function ?

It should be like :

 HANDLE m_hDevMode;
 HANDLE m_hDevNames;

GetPrinterDevice(_T("HP LaserJet III"), &m_hDevNames, &m_hDevMode);

.....



Correct usage is shown on following KB article. follow this :

How to modify the "default" printer for your Microsoft Foundation Classes (MFC) application to be other than the actual system-defined default printer :
http://support.microsoft.com/kb/193103 <=====================

-MAHESH
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 17918833
The most likely reason for that error is that, during the preceding code, the on-stack values of one or more of the pointer variables has been inadvertantly modified.  To test that, place a breakpoint on the first line of the GetPrinterDevice function.  At that point, examine and write down that values of the two pointer variables.  Single-step the function and see where the values get overwritten.  It's probably during one of the memcpy calls.

-- Dan
0
 
LVL 22

Expert Comment

by:mahesh1402
ID: 17925104
wdhough,
 So how you solved your problem ? above kb article helped you ??

-MAHESH
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 

Author Comment

by:wdhough
ID: 17928609
Yeah the above article solved it, i was using that approach all along i just couldnt get it to work and its because i was passing the wrong HANDLE objects.

Hope this helps

Will
0
 
LVL 22

Expert Comment

by:mahesh1402
ID: 17928874
well then if it solved with above then why grade 'B' for ?
0
 

Author Comment

by:wdhough
ID: 17928929
sorry i am new to the site, the code supplied didnt completely solve the problem but rather showed me the error so i had to find some other HANLDE objects in my application and pass them.  Anyway b said "Very good" i think which i though your answer was.  does a b grade mean something else then?
0

Featured Post

New feature and membership benefit!

New feature! Upgrade and increase expert visibility of your issues with Priority Questions.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This is to be the first in a series of articles demonstrating the development of a complete windows based application using the MFC classes.  I’ll try to keep each article focused on one (or a couple) of the tasks that one may meet.   Introductio…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
We’ve all felt that sense of false security before—locking down external access to a database or component and feeling like we’ve done all we need to do to secure company data. But that feeling is fleeting. Attacks these days can happen in many w…

972 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question