Solved

Select Printer Programmatically Problem

Posted on 2006-11-10
6
813 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 500 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
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 

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

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
function returning CString in a regular win32 DLL 8 188
fizzArray2 challenge 1 88
modThree challenge 4 96
Dell Alienware Graphics Amplifier Driver for non-Alienware systems 18 336
Introduction: Finishing the grid – keyboard support for arrow keys to manoeuvre, entering the numbers.  The PreTranslateMessage function is to be used to intercept and respond to keyboard events. Continuing from the fourth article about sudoku. …
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
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.
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…

791 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