>>>Jonathan Pryor <[EMAIL PROTECTED]> 09/06/04 4:57 pm >>>
 
>Correctness depends upon the ListLocalPrinters() documentation.  What is
>`printerList' supposed to be?  Just a pointer to a
>CupsPrinterListStruct*?  Or should it be an array of pointers?  How many
>elements will be addressed?
 
Thanks for your insights and observations - very informative.  As you
deduced, "printerList" is a pointer to a CupsPrinterListStruct*.  I
modified the wrapper implementation to use "unsafe" code but still
unsuccessful in retrieving properties from the C# structure below.
The unmanaged ListLocalPrinters is returning a list containing 1
element yet the loop in PrintLibWrapper.ListLocalPrinters is executed
twice, throwing a NullReferenceException when "printer = printer->nextElement"
is executed on the second pass.  Further, a NullReferenceException is
thrown on the first iteration through the loop by simply invoking
"Console.WriteLine("PrinterInfo: {0}, {1}", pl.Name, pl.Uri)".
I have tried several attributes on the structure elements with no change
in behavior.  I believe the problem is in the marshalling attributes, but
I have yet to discover how to examine the memory in mono on linux.
Installing/configuring a windows client and running/debugging there
may be the easiest path.
 
Thanks again for the help.
Jim
 
// interop struct
[ StructLayout(LayoutKind.Sequential) ]
private�unsafe�struct�InternalPrinterList
{
   [MarshalAs(UnmanagedType.ByValTStr/*LPStr*/, SizeConst=1024)]
   public string printerUri;
 
   [MarshalAs(UnmanagedType.ByValTStr/*LPStr*/, SizeConst=1024)]
   public string printerCupsUri;
 
   [MarshalAs(UnmanagedType.ByValTStr/*LPStr*/, SizeConst=1024)]
   public string printerName;
 
   [MarshalAs(UnmanagedType.ByValTStr/*LPStr*/,SizeConst=81)]
   public�string�printerMakeModel;
 
   [MarshalAs(UnmanagedType.U4)]
   public InternalPrinterList *nextElement;
}
 
// Convert linked list constructed by unmanaged code to
// array of user-visible PrinterList objects.
public static unsafe PrinterList[] ListLocalPrinters()
{
   IntPtr list = IntPtr.Zero;
   try
   {
      ListLocalPrinters(ref list);
      InternalPrinterList* printer = (InternalPrinterList *)list;
      ArrayList printers = new ArrayList();
      while (printer != null)
      {
         PrinterList pl = new PrinterList();
         pl.Uri = printer->printerUri;
         pl.CupsUri = printer->printerCupsUri;
         pl.Name = printer->printerName;
         pl.MakeModel = printer->printerMakeModel;
         // throws NullReferenceException
         Console.WriteLine("PrinterInfo: {0}, {1}", pl.Name, pl.Uri);
 
         printers.Add(pl);
         // Something not right here as we will go through again
         // even when list contains only 1 element.
         printer = printer->nextElement;
       }
       PrinterList[] rval = new PrinterList[printers.Count];
       printers.CopyTo(rval);
       return rval;
   }
   catch (Exception e)
   {
       return new PrinterList[0];
   }
   finally
   {
      if (list != IntPtr.Zero)
         FreeLocalPrinterList(list);
   }
}

Reply via email to