Thread: Error trying to use function EnumPrinters()[C - WIN32 API]

  1. #1
    Registered User HelpfulPerson's Avatar
    Join Date
    Jun 2013
    Location
    Over the rainbow
    Posts
    288

    Error trying to use function EnumPrinters()[C - WIN32 API]

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    
    
    #define WIN_32_LEAN_AND_MEAN
    #include <windows.h>
    #include <strsafe.h>
    
    
    #define FILE_NAME "file.txt"
    
    
    void ErrorExit(LPTSTR lpszFunction)
    {
        /* Retrieve the system error message for the last-error code */
    
    
        LPVOID lpMsgBuf;
        LPVOID lpDisplayBuf;
        DWORD dw = GetLastError();
    
    
        FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER |
            FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL,
            dw,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPTSTR) &lpMsgBuf,
            0, NULL );
    
    
        lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
            (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
        StringCchPrintf((LPTSTR)lpDisplayBuf,
            LocalSize(lpDisplayBuf) / sizeof(TCHAR),
            TEXT("%s failed with error %d: %s"),
            lpszFunction, dw, lpMsgBuf);
        MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
    
    
        LocalFree(lpMsgBuf);
        LocalFree(lpDisplayBuf);
        ExitProcess(dw);
    }
    
    
    int main( )
    {
        BOOL returnValue = FALSE;
        PBYTE printerInfo;
        LPDWORD bytesCopied = NULL;
        LPDWORD bytesNeeded = NULL;
        FILE * newFile = NULL;
    
    
        newFile = fopen(FILE_NAME, "w+");
        printerInfo = malloc(sizeof(PRINTER_INFO_4));
    
    
        if ( printerInfo == NULL )
        {
            perror("Malloc");
            exit(1);
        }
    
    
        if ( newFile == NULL )
        {
            perror("Creating file");
            exit(1);
        }
    
    
        returnValue = EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, printerInfo, sizeof(PRINTER_INFO_4), bytesNeeded, bytesCopied );
    
    
        if ( !returnValue )
        {
            ErrorExit(TEXT("EnumPrinters"));
            free(printerInfo);
            exit(1);
        }
    
    
        fclose(newFile);
        if ( remove(FILE_NAME) ) perror("Deleting file");
    
    
        free(printerInfo);
    
    
        return 0;
    }
    I decided to try to make my own code for printing a text document on the local printer. I've written some code to create a temporary text file( I haven't gotten to the actual printing yet, so I'm leaving it empty) also. My problem is EnumPrinters fails with error 1780 :

    "A null reference was passed to the stub"

    I have no idea what that is talking about, since I don't understand what it refers to when it says "stub". Can someone help me understand what's wrong with this code?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    EnumPrinters function (Windows)

    Notice this part.
    _Out_ LPDWORD pcbNeeded,
    _Out_ LPDWORD pcReturned

    Now look at your code.
    LPDWORD bytesCopied = NULL;
    LPDWORD bytesNeeded = NULL;
    ...
    returnValue = EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, printerInfo, sizeof(PRINTER_INFO_4), bytesNeeded, bytesCopied );


    > "A null reference was passed to the stub"
    Can you see it yet?


    You can't just go around declaring variables which match the function prototype, you have to think about how those parameters are going to be used.

    Do you know what the annotation _Out_ even means?
    It means that the function is expecting to WRITE data to some variable of yours to deliver information you need.

    So what you should really be doing is something like
    DWORD bytesCopied = 0;
    DWORD bytesNeeded = 0;
    ...
    returnValue = EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, printerInfo, sizeof(PRINTER_INFO_4), &bytesNeeded, &bytesCopied );


    Unless the documentation specifically states that NULL is an acceptable value for an out parameters, you need to be passing a pointer to valid memory in all cases.
    That means if the function expects LPTYPE, you should be declaring TYPE var; and passing &var as the parameter.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User HelpfulPerson's Avatar
    Join Date
    Jun 2013
    Location
    Over the rainbow
    Posts
    288
    Quote Originally Posted by Salem View Post
    EnumPrinters function (Windows)

    Notice this part.
    _Out_ LPDWORD pcbNeeded,
    _Out_ LPDWORD pcReturned

    Now look at your code.
    LPDWORD bytesCopied = NULL;
    LPDWORD bytesNeeded = NULL;
    ...
    returnValue = EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, printerInfo, sizeof(PRINTER_INFO_4), bytesNeeded, bytesCopied );


    > "A null reference was passed to the stub"
    Can you see it yet?


    You can't just go around declaring variables which match the function prototype, you have to think about how those parameters are going to be used.

    Do you know what the annotation _Out_ even means?
    It means that the function is expecting to WRITE data to some variable of yours to deliver information you need.

    So what you should really be doing is something like
    DWORD bytesCopied = 0;
    DWORD bytesNeeded = 0;
    ...
    returnValue = EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, printerInfo, sizeof(PRINTER_INFO_4), &bytesNeeded, &bytesCopied );


    Unless the documentation specifically states that NULL is an acceptable value for an out parameters, you need to be passing a pointer to valid memory in all cases.
    That means if the function expects LPTYPE, you should be declaring TYPE var; and passing &var as the parameter.
    Oh, that clears it up Salem. I see what you're saying, I can't receive a value when there is no memory to store it in. Thanks.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Win32 API Icon Loading Error (VS2010)
    By William Putnam in forum C++ Programming
    Replies: 2
    Last Post: 07-09-2013, 02:16 PM
  2. Win32 Resource File Error (C++)
    By goldentoa11 in forum Windows Programming
    Replies: 3
    Last Post: 04-06-2011, 01:39 PM
  3. Cause of a Win32 error
    By CDdotdot47 in forum C Programming
    Replies: 7
    Last Post: 07-02-2010, 05:59 PM
  4. win32 timer function
    By Anuradh_a in forum Windows Programming
    Replies: 2
    Last Post: 03-04-2008, 11:51 AM
  5. using 'cin' like function in win32 application.
    By blacksheep in forum C++ Programming
    Replies: 2
    Last Post: 01-30-2003, 02:49 PM