JNA Implementierungsproblem

Hallo, ich bin neu in diesem Forum und schon gleich ein Problem bei der implementierung einer Windows API Funktion über JNA.
Ich habe die Frage schon in einem anderen Forum gestellt um dort Aushilfe zu bekommen aber nicht mal die kleinste Reaktion deswege lege ich meine Hoffnung auf dieses Forum. :slight_smile:

Nun:
Ich bin dabei ein Print Management System zu entwickeln das dazu dient Druck aufträge freizugeben oder zu blockieren sowie diverse andere Funktionen.
Das Problem allerdings ist dass ich noch nicht soviel Erfahrung habe was JNA angeht und deswegen bitte ich darum dass mir vieleicht jemand aushelfen kann.

Mein Problem liegt bei der Implementierung zweier DatenTypen: LPDEVMODE und PSECURITY_DESCRIPTOR ich tue mich sehr schwer.

Devmode:

PSECURITY_DESCRIPTOR
Keine definition direkt gefunden wie implementiere ich diese bzw. welcher Datentyp?

Hier die aktuelle Implementierung bis auf diese beiden Datentypen.

     
    import java.util.Arrays;
    import java.util.List;
     
    import com.sun.jna.Memory;
    import com.sun.jna.Native;
    import com.sun.jna.Structure;
    import com.sun.jna.platform.win32.WinBase.SYSTEMTIME;
    import com.sun.jna.platform.win32.WinDef.DWORD;
    import com.sun.jna.platform.win32.WinNT.HANDLE;
    import com.sun.jna.ptr.IntByReference;
    import com.sun.jna.win32.StdCallLibrary;
    import com.sun.jna.win32.W32APIOptions;
     
     
    /*
     * typedef struct _JOB_INFO_2 {
      DWORD                JobId;
      LPTSTR               pPrinterName;
      LPTSTR               pMachineName;
      LPTSTR               pUserName;
      LPTSTR               pDocument;
      LPTSTR               pNotifyName;
      LPTSTR               pDatatype;
      LPTSTR               pPrintProcessor;
      LPTSTR               pParameters;
      LPTSTR               pDriverName;
      LPDEVMODE            pDevMode;
      LPTSTR               pStatus;
      PSECURITY_DESCRIPTOR pSecurityDescriptor;
      DWORD                Status;
      DWORD                Priority;
      DWORD                Position;
      DWORD                StartTime;
      DWORD                UntilTime;
      DWORD                TotalPages;
      DWORD                Size;
      SYSTEMTIME           Submitted;
      DWORD                Time;
      DWORD                PagesPrinted;
    } JOB_INFO_2, *PJOB_INFO_2;
     */
     
    public interface WinPrintJobs extends StdCallLibrary{
       
        WinPrintJobs INSTANCE = (WinPrintJobs) Native.loadLibrary("Winspool.drv", WinPrintJobs.class, W32APIOptions.UNICODE_OPTIONS);
       
        public static class _JOB_INFO_2 extends Structure {
     
              public int     JobId;
              public String  pPrinterName;
              public String  pMachineName;
              public String  pUserName;
              public String  pDocument;
              public String  pNotifyName;
              public String  pDatatype;
              public String  pPrintProcessor;
              public String  pParameters;
              public String  pDriverName;
              //LPDEVMODE            pDevMode;
              public String  pStatus;
              //PSECURITY_DESCRIPTOR pSecurityDescriptor;
              public int     Status;
              public int     Priority;
              public int     Position;
              public int     StartTime;
              public int     UntilTime;
              public int     TotalPages;
              public int     Size;
              SYSTEMTIME     Submitted;
              public int     Time;
              public int     PagesPrinted;
     
            @Override
            protected List<? > getFieldOrder() {
                return  Arrays.asList(new String[] {"JobId", "pPrinterName", "pMachineName", "pUserName","pDocument","pNotifyName",
                                                    "pDatatype", "pPrintProcessor", "pParameters", "pDriverName", "pDevMode",
                                                    "pStatus", "pSecurityDescriptor", "Status", "Priority", "Position","StartTime",
                                                    "UntilTime", "TotalPages", "Size", "Time", "PagesPrinted"
                                                    });
            }
           
            public _JOB_INFO_2() {
               
            }
           
            public _JOB_INFO_2(int size) {
                super(new Memory(size));
            }  
           
            //Fetch Printer Jobs
     
        }
       
        boolean  EnumJobs(HANDLE spooler, DWORD FirstJob, DWORD NoJobs, int level, IntByReference pRef3, int cBuf, IntByReference pcbNeeded, IntByReference pcReturned );
     
    }```

Vielen Dank im voraus.
Fox

Das ist eine sehr spezielle und sehr schwierige Frage, deswegen ist das nicht sooo verwunderlich. Und diese struct ist … blarg, da muss IMHO jemand schon sehr lange sehr viel Mist gebaut haben, damit sowas rauskommt :sick: Aber… schon die struct, die du da hast, sieht ja ähnlich cranck aus. Erst hatte ich die Möglichkeit in Betracht gezogen, dass eine Schwierigkeit bei den Unions liegen könnte, aber einer schnellen Websuche nach ( z.B: (!) Redirecting… ) sollte JNA die ja nachtlos verarbeiten können. Kritischer wird da wohl schon das #ifdef. Theoretisch müßte man dafür vermutlich (!) im schlimmsten Fall mehrere Strukturen erstellen, und je nach Windows-Version die passende verwenden - was ein ziemlicher Krampf wäre, aber … vielleicht kann man die Frage eingrenzen?

Hey,

Nun das problem liegt darin dass ich andern falls nicht an die informationen komme die ich brauche es sei denn ich kann diese beiden Datentypen weglassen?
Oder muss es wirklich exact genau au den Punkt so implementiert werden dass ALLES enthalen ist damit ich es in Java nutzen kann?

Ich kann mir vortstellen dass es wirklich nicht einfach ist, und ich bisher auch noch nicht wirklich eine Lösung gefunden habe bezüglich diesen beiden Datentypen die mir schmerzen machen.

Der Quellcode oder die Struct von MS von der API?

Die struct die ich gepostet habe, habe ich zusammen gesetzt bis halt auf die beiden infos.
Ich hoffe jemand anders hat vieleicht noch eine Hilfestellung. :slight_smile:

Gruss

Sorry, da könnte ich spontan nur sagen: „Ausprobieren“ :o (Ich meinte übrigens die Struct aus der MS-API… vielleicht bin ich ja von Java verwöhnt, aber selbst wenn das eine Klasse wäre, würde ich sagen: Hui, das sollte man vielleicht nochmal überdenken…)

Im schlimmsten Fall die Header aus der Windows API direkt ansehen und nachbauen. Windows Platform SDK runterladen und go :wink:

PS: Nur weil man JNA nutzen will heißt es nicht, dass man deswegen die Header nicht mehr braucht g

[QUOTE=Noctarius]Im schlimmsten Fall die Header aus der Windows API direkt ansehen und nachbauen. Windows Platform SDK runterladen und go :wink:

PS: Nur weil man JNA nutzen will heißt es nicht, dass man deswegen die Header nicht mehr braucht g[/QUOTE]

OK darauf bin ich jetzt nicht gekommen wäre das der einfachste weg als mit JNA zu arbeiten?
Ehrlich gesagt habe ich nie mit der Windows SDK gearbeitet, habe gerade ein wenig gegoogelt und geschaut ob es irgendwelche Java basierten tutorials gibt aber leider nicht wirklich was gefunden.
Hast du vieleicht eine gute Quelle?

Ich bin ehrlich gesagt ein bisschen hilflos weil ich absolut nicht weiss wie ich an diese Funktionen vom drucker kommen soll, Java hat zwar ein paar methoden aber nicht die Informationen welche ich brauche. :-((

Gruss

Das Windows Platform SDK sind hauptsächlich die C++ Header Dateien um mit C++ für Windows programmieren, aber genau diese Header definieren Structs, Konstanten und Methoden die du brauchst um diese über JNA in Java abzubilden. Natürlich kannst du auch mit JNI auf die Windows API zugreifen (dann brauchst du die Windows Header sowieso zum kompilieren des C++ Code), ich würde aber bei JNA (alternativ JNR) bleiben.

Das Platform SDK findest du hier: Download Microsoft Windows SDK for Windows 7 and .NET Framework 4 from Official Microsoft Download Center

Was du sowohl mit JNA als auch mit JNR nicht so ohne weiteres kannst sind Instanzen von C++ Klassen zu erstellen, du kannst quasi nur „statische“ Methoden aufrufen, das reicht für gute 80% der Windows API aber.

*** Edit ***
PPS:
DEVMODE: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183565(v=vs.85).aspx
PSECURITY_DESCRIPTOR: I would just try to use a pointer since the best advice is to not modify it anyways :slight_smile:

Der Security_descriptor hab ich jetzt gebacken bekommen nun noch den Struct DevMod und das ist schon richtig Kopfschmerzen.
OK C++ Header soweit so gut allerdings muss ich dann JNI nutzen um diese aufzurufen JNA da lande ich genau da wo ich jetzt hänge bei der Implementierung dieses Structs :-).

Ich denke wenn ich das ganze jetzt umbauen gehe werde ich JNA nicht mehr brauchen da ich nicht an die Infos komme an die ich eigentlich ran möchte.
Also bleibt mir eigentlich nur die information mit JNI auf die Header direkt zuzugreifen?
Wie gesagt Devmod muss implementiert werden.

Oder habe ich was falsch verstanden?

Gruss

Du schaust dir die Header an und baust die mit JNA!

Ach Leute, man könnte doch erstmal naiv mit dem hier anfangen : http://msdn.microsoft.com/en-us/library/windows/desktop/dd145020(v=vs.85).aspx
Das ist der Aufbau von JOB_INFO_2, man könnte auch in Java-Term sagen : die Signatur.
Dann kann man mal in JNA nachgucken und sollte dann finden das JNA bereits Winspool zur Verfügung stellt. Also kann man sich dann hier abgucken wie es gehen müsste.
Allerdings wird nur PRINTER_INFO_1 und PRINTER_INFO_4 angeboten. Die kann man sicher aber auch im MSDN raussuchen :
http://msdn.microsoft.com/en-us/library/windows/desktop/dd162844(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd162847(v=vs.85).aspx
Dann hat man erstmal ne grobe Vorstellung wie es korrekt aussehen müsste. Erster Fehler der mir hier erstmal auffällt : du hast die Klasse falsch benannt. In deinem Code steht JOB_INFO_2, laut dem JNA-Beispiel müsste es aber erstmal nur JOB_INFO_2 heißen, ohne den führenden "".

So, dann liest man die Doc mal weiter. DEVMODE ist direkt verlinkt und sieht so aus : http://msdn.microsoft.com/en-us/library/windows/desktop/dd183565(v=vs.85).aspx
Ist also in der Java-Implementierung nur eine weitere innere Klasse vom Type Structure mit dem Namen DEVMODE.

Zu pSecurityDescriptor steht lediglich das es eine Null-Referenz wäre. Hier würde ich einfach einen Pointer nehmen und ihn mit NULL belegen. Sollte der Doc im MSDN gerecht werden.

Die grobe Struktur dürfte dann also ungefähr so in folgende Richtung aussehen :

{
	public static class JOB_INFO_2 extends Structure
	{
		public static class DEVMODE extends Structure
		{
		}
	}
}```

Bezüglich der in DEVMODE vorhandenen Union und Struct müsste es dann laut StackOverflow so aussehen :
```public static class DEVMODE extends Structure
{
	public static class XXX extends Union
	{
		public static class XXX extends Structure
		{
		}
	}
}```
Problem ist hierbei nur das weder die Union noch die Struct einen Namen haben weshalb ihre Implementierung in Java so sicher ziemlich umständlich werden dürfte (hab jetzt nicht weiter gegoogled was man in diesem Fall macht).
Auch dürfte die Umsetzung des Prä-Prozessor-#IF problematisch werdenda sich hier ja was im gegensatz zu Java stark unterscheidet : der Prä-Prozessor verändert den Source selbst direkt vor dem Compilen. Man muss also wissen auf welcher Windows-Version man läuft um entsprechende Klassen laden da halt in älteren Versionen gewisse Felder nicht vorhanden sind.

Man könnte auch, soweit ich gelesen habe, die unbenannten Union und Struct komplett auflösen und fügt deren Member dann einfach dem nächst höheren benannten hinzu, so das also das mit dem Union und Strucutre einfach ersatzlos rausfallen würde.


- nach etwas googlen -

Ähm, bezüglich das mit dem SECURITY_DESCRIPTOR : ist bereits in JNA vorhanden : com.sun.jna.platform.win32.WinNT.SECURITY_DESCRIPTOR

Demnach kann man das ganze dann doch recht einfach implementieren :

```public interface Winspool extends StdCallLibrary
{
	Winspool INSTANCE=(Winspool)Native.loadLibrary("Winspool.drv", Winspool.class, W32APIOptions.UNICODE_OPTIONS);
	public static class JOB_INFO_2 extends Structure
	{
		public int JobId;
		public String pPrinterName;
		public String pMachineName;
		public String pUserName;
		public String pDocument;
		public String pNotifyName;
		public String pDatatype;
		public String pPrintProcessor;
		public String pParameters;
		public String pDriverName;
		DEVMODE pDevMode;
		public String pStatus;
		WinNT.SECURITY_DESCRIPTOR pSecurityDescriptor;
		public int Status;
		public int Priority;
		public int Position;
		public int StartTime;
		public int UntilTime;
		public int TotalPages;
		public int Size;
		SYSTEMTIME Submitted;
		public int Time;
		public int PagesPrinted;
		
		public static class DEVMODE extends Structure
		{
			// ... entsprechend http://msdn.microsoft.com/en-us/library/windows/desktop/dd183565(v=vs.85).aspx
		}
	}
}```
Das wäre jetzt mal so meine Idee. Wie man nun letzten Endes DEVMODE richtig implementiert, also das mit den unbenannten union und struct sollte man entweder noch mal Google fragen oder sich ein entsprechends Fach-Forum (z.B. JavaRanch) suchen. Aber so in etwas sollte das dann hinhauen.

Super,
vielen Dank für die freundlichen Antworten werde mich dann wieder dahinter setzen und dann später das fertig Projekt posten für Feedbacks u.s.w
Bis dahin nochmal vielen Dank.

Gruss Fox