winspool.drv calls to remote computer gives access denied. Need help how to authenticate

I am getting printer drivers enumeration from a computer by calling EnumPrinterDrivers in winspool.drv and it works just great using the code below, but when I try to get it from a computer outside my domain or where my credentials are not right i get "access denied" (that is of course a obvious behaviour). My question is how can I create a connection "authenticate" to the computer prior to calling EnumPrinterDrivers with correct username and password. It has to be done in code.

are there some .net functionallity that solves this for me or are there any dll-functions that I can do to authenticate to the remote system.

I am using 2005

here is the code that works just fine except for connecting to computers with other credentials.

------------------- Start Dll-function declaration  --------------------
  ' Declaration
  Private Overloads Declare Function EnumPrinterDrivers Lib "winspool.drv" Alias "EnumPrinterDriversA" ( _
    ByVal pName As String, _
    ByVal pEnvironment As String, _
    ByVal Level As Int32, _
    ByVal pDriverInfo As IntPtr, _
    ByVal cpBuf As Int32, _
    ByRef pcbNeeded As Int32, _
    ByRef pcReturned As Int32 _
  ) As Int32

------------------- End Dll-function declaration  --------------------

------------------- Start main code --------------------

    Dim iReturn As Int32
    Dim pcbNeeded As Int32
    Dim pcReturned As Int32
    Dim bufDriver As IntPtr
    Dim iCount As Int32
    Dim diDriverInfo As DRIVER_INFO_3 = New DRIVER_INFO_3
    Dim serverName As String = ""      ' empty for local computer
    Dim environment As String = ""     ' empty for all

      iReturn = EnumPrinterDrivers(serverName, environment, 3, bufDriver, 0, pcbNeeded, pcReturned)
      If pcbNeeded > 0 Then
        bufDriver = Marshal.AllocHGlobal(pcbNeeded)
        iReturn = EnumPrinterDrivers(serverName, environment, 3, bufDriver, pcbNeeded, pcbNeeded, pcReturned)

        Dim lpNext As IntPtr
        lpNext = bufDriver
        For iCount = 1 To pcReturned
          Marshal.PtrToStructure(lpNext, diDriverInfo)
          lpNext = New IntPtr(lpNext.ToInt32 + Marshal.SizeOf(diDriverInfo))
              debug.print diDriverInfo.pName
        Throw New Win32Exception(Marshal.GetLastWin32Error())

      End If
    Catch ex As Win32Exception
    End Try

------------------- End main code ---------------------

-------- Start Driver info declaration class -------------

'DRIVER_INFO_3 structure
<StructLayout(LayoutKind.Sequential)> _
    Public Class DRIVER_INFO_3
  Public cVersion As Int32
  Public pName As String
  Public pEnvironment As String
  Public pDriverPath As String
  Public pDataFile As String
  Public pConfigFile As String
  Public pHelpFile As String
  Public pDependentFiles As String
  Public pMonitorName As String
  Public pDefaultDataType As String
End Class

-------- End Driver info declaration class -------------

/ Mikael
Mikael JanssonAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Bob LearnedCommented:
What information are you using with EnumPrinterDrivers?  You can get a lot of information easily with WMI, using the Win32_Printer class.

Mikael JanssonAuthor Commented:
It is actually only a little part of the system I am building. I am using a lot of WMI already but I need to delete single jobs from a print queue, delete drivers (incl. files) from a computer (even remote). In WMI I know that I can do remote connect quite easy but it seams that WMI has some limitations when for example need to remove a single job from a queue etc.

/ Mikael
Bob LearnedCommented:
This is what I was talking about with the Win32_Printer class:

' Add a reference to System.Management.dll to the project.

Imports System.Management

Public Enum PrinterStatus
  Other = 1
End Enum 'PrinterStatus

Public Class Win32_Printer

  Public DriverName As String
  Public IsNetwork As Boolean
  Public IsShared As Boolean
  Public PortName As String
  Public PrinterLocation As String
  Public PrinterName As String
  Public ServerName As String
  Public ShareName As String
  Public Status As PrinterStatus
  Public WorkOffline As Boolean

  Public Overloads Shared Function GetList() As Win32_Printer()
    Return GetList(Nothing)
  End Function  'GetList

  Public Overloads Shared Function GetList(ByVal machineName As String, ByVal userName As String, ByVal userPassword As String) As Win32_Printer()

    Dim options As New ConnectionOptions
    options.Username = userName
    options.Password = userPassword

    Dim path As New ManagementPath
    path.Server = "\\" & machineName.TrimStart("\") & "\root\cimv2"

    Dim scope As New ManagementScope(path)
    scope.Options = options

    ' Remote machine
    Return GetList(scope)

  End Function   'GetList(machine, user, password)

  Public Overloads Shared Function GetList(ByVal scope As ManagementScope) As Win32_Printer()

    Dim query As String = "Select * From Win32_Printer"

    Dim searcher As New ManagementObjectSearcher(query)

    If Not scope Is Nothing Then
      searcher.Scope = scope
    End If

    Dim listPrinters As New ArrayList

    For Each entryCurrent As ManagementObject In searcher.Get()

      Dim printer As New Win32_Printer

      printer.DriverName = entryCurrent("DriverName")
      printer.IsNetwork = entryCurrent("Network")
      printer.IsShared = entryCurrent("Shared")
      printer.PortName = entryCurrent("PortName")
      printer.PrinterLocation = entryCurrent("Location")
      printer.PrinterName = entryCurrent("Name")
      printer.ServerName = entryCurrent("ServerName")
      printer.ShareName = entryCurrent("ShareName")
      printer.Status = Convert.ToInt32(entryCurrent("PrinterStatus"))
      printer.WorkOffline = entryCurrent("WorkOffline")


    Next entryCurrent

    Return CType(listPrinters.ToArray(GetType(Win32_Printer)), Win32_Printer())

  End Function  'GetList

End Class
Get expert help—faster!

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

Bob LearnedCommented:
Notice the DriverName property.

Mikael JanssonAuthor Commented:
I am using similar code already for enumeration of printers but as far as I know WMI can not handle delete of printer drivers including all depending files, thats the main reason why I am using winspool.drv functions. But if you know a simpler way with WMI to do that I all ears. This also for cancel a specific job in a queue, all I could find in WMI is to "CancelAllJobs" and thats not what I am looking for.

I also noticed a performance difference between WMI and winspool.drv calls when enumerating e.g. printers or drivers, winspool.drv calls was faster

/ Mikael

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Mikael JanssonAuthor Commented:
Hi TheLearnedOne,
I might have been digging to deep to test things so I forgot to answer back here, sorry for that. Your last answer is probably solving my issue but I still have some things that is still not working but of course you earned your points so I will accept the answer.

Thanks for your help and sorry that I forgot to get back to finish the question

/ Mikael
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.