Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

Select Printer Programmatically Problem

Posted on 2006-11-10
6
Medium Priority
?
848 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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

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

Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

Question has a verified solution.

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

Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
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 summaries big data hadoop online training demo (http://onlineitguru.com/big-data-hadoop-online-training-placement.html) , and covers basics in big data hadoop .
Suggested Courses
Course of the Month11 days, 14 hours left to enroll

564 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