Seite 1 von 1

Portadresse ausgeben?

Verfasst: 13.02.2010 21:34
von Falko
Ich suche nach einer Möglichkeit die Portadressen von LPT zu ermitteln.
Da bei mir im PC kein LPT vorhanden war, habe ich mir eine PCI-Karte mit zwei LPT-Anschlüssen gekauft.
Ich weiß, das sie mit $E080 bzw. $E480 aufgerufen werden können. Mir wäre es aber lieber, erstmal
vorhandene LPT-Schnittstellen aufzulisten und dazu die Adressen.

Zum ersteren habe ich hier was schönes von Danilo gefunden und etwas korrigiert:

Code: Alles auswählen

;Source aus dem englischen Forum Danilo
;http://www.purebasic.fr/english/viewtopic.php?p=24276#p24276

Dim buffer.PORT_INFO_2(1000)

pcbNeeded.l=0
pcReturned.l=0

!PUSH dword v_pcReturned
If EnumPorts_(#Null,2,@buffer(),SizeOf(PORT_INFO_2)*1000,@pcbNeeded.l,@pcReturned)
  For a = 0 To pcReturned-1
    If buffer(a)\pPortName
      Debug "FOUND:  "+PeekS(buffer(a)\pPortName)
      Debug "    - "  +PeekS(buffer(a)\pMonitorName)
      Debug "    - "  +PeekS(buffer(a)\pDescription)
      Select buffer(a)\fPortType
        Case #PORT_TYPE_WRITE        : Debug "    - "+"PORT_TYPE_WRITE"
        Case #PORT_TYPE_READ         : Debug "    - "+"PORT_TYPE_READ"
        Case #PORT_TYPE_REDIRECTED   : Debug "    - "+"PORT_TYPE_REDIRECTED"
        Case #PORT_TYPE_NET_ATTACHED : Debug "    - "+"PORT_TYPE_NET_ATTACHED"
      EndSelect
    EndIf
  Next a
  Debug "END."
Else
  Error$ = Space(1000)
  FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM,#FORMAT_MESSAGE_FROM_HMODULE,GetLastError_(),0,Error$,Len(Error$),0)
  MessageRequester("ERROR",Error$,#MB_ICONERROR)
EndIf


Nur fehlen hier die Portadressen, welche die Structure nicht anbietet. Gibt es da evtl. noch eine andere Möglichkeit?
Ich würde mich sehr freuen, wenn ihr mir da weiterhelfen könntet.

Grüße, Falko

Re: Portadresse ausgeben?

Verfasst: 20.02.2010 20:23
von DarkDragon
Hallo,

Das hier läuft zumindest unter 32bit und laut dir ja auch unter 64bit:

Code: Alles auswählen

EnableExplicit

Prototype.i CM_Get_First_Log_Conf_(plcLogConf.i, dnDevInst.l, ulFlags.l)
Prototype.i CM_Get_Next_Res_Des_(prdResDes.i, rdResDes.i, ForResource.l, pResourceID.i, ulFlags.i)
Prototype.i CM_Free_Res_Des_Handle_(rdResDes.i)
Prototype.i CM_Get_Res_Des_Data_Size_(pulSize.i, rdResDes.i, ulFlags.i)
Prototype.i CM_Get_Res_Des_Data_(rdResDes.i, *Buffer, BufferLen.i, ulFlags.i)
Prototype.i CM_Get_Device_ID_(dnDevInst.i, *Buffer, BufferLen.i, ulFlags.i)

Global CM_Get_First_Log_Conf.CM_Get_First_Log_Conf_
Global CM_Get_Next_Res_Des.CM_Get_Next_Res_Des_
Global CM_Free_Res_Des_Handle.CM_Free_Res_Des_Handle_
Global CM_Get_Res_Des_Data_Size.CM_Get_Res_Des_Data_Size_
Global CM_Get_Res_Des_Data.CM_Get_Res_Des_Data_
Global CM_Get_Device_ID.CM_Get_Device_ID_
Global Cfgmgr32

Cfgmgr32 = OpenLibrary(#PB_Any, "cfgmgr32.dll")
If Cfgmgr32
  CM_Get_First_Log_Conf     = GetFunction(Cfgmgr32, "CM_Get_First_Log_Conf")
  CM_Get_Next_Res_Des       = GetFunction(Cfgmgr32, "CM_Get_Next_Res_Des")
  CM_Free_Res_Des_Handle    = GetFunction(Cfgmgr32, "CM_Free_Res_Des_Handle")
  CM_Get_Res_Des_Data_Size  = GetFunction(Cfgmgr32, "CM_Get_Res_Des_Data_Size")
  CM_Get_Res_Des_Data       = GetFunction(Cfgmgr32, "CM_Get_Res_Des_Data")
  CM_Get_Device_ID          = GetFunction(Cfgmgr32, "CM_Get_Device_IDA")
EndIf

Structure SP_DEVINFO_DATA
  cbSize.l
  ClassGuid.GUID
  DevInst.l
  Reserved.i ; ULONG_PTR
EndStructure

Structure IO_DES
  IOD_Count.l
  IOD_Type.l
  IOD_Alloc_Base.q
  IOD_Alloc_End.q
  IOD_DesFlags.l
EndStructure

Structure IO_RANGE
  IOR_Align.q
  IOR_nPorts.l
  IOR_Min.q
  IOR_Max.q
  IOR_RangeFlags.l
  IOR_Alias.q
EndStructure


#SPDRP_CLASS         = $00000007
#SPDRP_FRIENDLYNAME  = $0000000C

#SPDIT_COMPATDRIVER  = 2

#ALLOC_LOG_CONF = $00000002
#BOOT_LOG_CONF  = $00000003

#CR_SUCCESS     = $00000000

#ResType_All                       = $00000000
#ResType_None                      = $00000000
#ResType_Mem                       = $00000001
#ResType_IO                        = $00000002
#ResType_DMA                       = $00000003
#ResType_IRQ                       = $00000004
#ResType_DoNotUse                  = $00000005
#ResType_BusNumber                 = $00000006
#ResType_MAX                       = $00000006
#ResType_Ignored_Bit               = $00008000
#ResType_ClassSpecific             = $0000FFFF
#ResType_Reserved                  = $00008000
#ResType_DevicePrivate             = $00008001
#ResType_PcCardConfig              = $00008002
#ResType_MfCardConfig              = $00008003

#MAX_PORTRANGES = 256

Structure SPORTRANGE
  RangeBegin.i
  RangeEnd.i
EndStructure

Structure SDEVICEINFO
  Class.s
  ClassDescription.s
  Name.s
  IOPortRangesCount.i
  IOPortRanges.SPORTRANGE[#MAX_PORTRANGES]
EndStructure

Global DevInfo

Procedure ExamineDevices()
  DevInfo = SetupDiGetClassDevs_(0, 0, 0, #DIGCF_PRESENT | #DIGCF_ALLCLASSES | #DIGCF_PROFILE)
EndProcedure

Procedure FinishDevices()
  SetupDiDestroyDeviceInfoList_(DevInfo)
  DevInfo = 0
EndProcedure

Procedure GetDeviceInformation(Index, *DeviceInformation.SDEVICEINFO)
  Protected *Buffer.IO_DES
  Protected RealSize.i
  Protected Result.i
  Protected CMResult.i
  Protected FirstLogConf.i, NextResDes.i, PrevResDes.i
  Protected DevInfoData.SP_DEVINFO_DATA

  Result = 0

  If *DeviceInformation And DevInfo
    *DeviceInformation\IOPortRangesCount = 0

    *Buffer = AllocateMemory(2048)

    If *Buffer
      DevInfoData\cbSize = SizeOf(SP_DEVINFO_DATA)
      If SetupDiEnumDeviceInfo_(DevInfo, Index, @DevInfoData)

        If SetupDiGetDeviceRegistryProperty_(DevInfo, @DevInfoData, #SPDRP_CLASS, 0, *Buffer, 2048, 0)
          *DeviceInformation\Class = PeekS(*Buffer)

          If SetupDiGetClassDescription_(@DevInfoData\ClassGuid, *Buffer, #MAX_PATH, @RealSize)
            *DeviceInformation\ClassDescription = PeekS(*Buffer)

            If SetupDiGetDeviceRegistryProperty_(DevInfo, @DevInfoData, #SPDRP_FRIENDLYNAME, 0, *Buffer, 2048, 0)
              *DeviceInformation\Name = PeekS(*Buffer)

              CMResult = CM_Get_First_Log_Conf(@FirstLogConf, DevInfoData\DevInst, #ALLOC_LOG_CONF)
              If CMResult <> #CR_SUCCESS
                CMResult = CM_Get_First_Log_Conf(@FirstLogConf, DevInfoData\DevInst, #BOOT_LOG_CONF)
              EndIf

              If CMResult = #CR_SUCCESS
                If CM_Get_Next_Res_Des(@NextResDes, FirstLogConf, #ResType_IO, 0, 0) = #CR_SUCCESS
                  Repeat
                    If CM_Get_Res_Des_Data_Size(@RealSize, NextResDes, 0) = #CR_SUCCESS
                      If RealSize > MemorySize(*Buffer)
                        *Buffer = ReAllocateMemory(*Buffer, RealSize)
                      EndIf
                      If *Buffer
                        CM_Get_Res_Des_Data(NextResDes, *Buffer, RealSize, 0)
                        If *Buffer\IOD_Count = 0
                          *DeviceInformation\IOPortRanges[*DeviceInformation\IOPortRangesCount]\RangeBegin = *Buffer\IOD_Alloc_Base
                          *DeviceInformation\IOPortRanges[*DeviceInformation\IOPortRangesCount]\RangeEnd   = *Buffer\IOD_Alloc_End
                          *DeviceInformation\IOPortRangesCount + 1
                        Else
                          ; I don't know if this would ever happen,
                          ; but then you'd have to read the buffer
                          ; in some special way as there's a whole
                          ; list of IO_RANGEs
                        EndIf
                      EndIf
                    EndIf

                    PrevResDes = NextResDes
                    CMResult   = CM_Get_Next_Res_Des(@NextResDes, PrevResDes, #ResType_IO, 0, 0)
                    CM_Free_Res_Des_Handle(PrevResDes)
                  Until CMResult <> #CR_SUCCESS
                EndIf

                CM_Free_Res_Des_Handle(FirstLogConf)
              EndIf
            EndIf
          EndIf
        EndIf
        
        Result = 1

        SetupDiDestroyDriverInfoList_(DevInfo, @DevInfoData, #SPDIT_COMPATDRIVER)
      EndIf
      
      If *Buffer
        FreeMemory(*Buffer)
      EndIf
    EndIf
  EndIf

  ProcedureReturn Result
EndProcedure

; ------------------------------ EXAMPLE CODE ---------------------------------------------------

Define Index
Define k
Define Text.s
Define DeviceInformation.SDEVICEINFO

ExamineDevices()
For Index = 0 To $7FFF
  If GetDeviceInformation(Index, @DeviceInformation)
    If DeviceInformation\Class = "Ports" And FindString(DeviceInformation\Name, "LPT", 1)
      Text = "(" + DeviceInformation\Class + ") " + DeviceInformation\Name
      For k = 0 To DeviceInformation\IOPortRangesCount - 1
        Text + "   ["
        Text + RSet(Hex(DeviceInformation\IOPortRanges[k]\RangeBegin, #PB_Integer), SizeOf(Integer), "0")
        Text + " - "
        Text + RSet(Hex(DeviceInformation\IOPortRanges[k]\RangeEnd , #PB_Integer), SizeOf(Integer), "0")
        Text + "] "
      Next k
      Debug Text
    EndIf
  EndIf
Next Index
FinishDevices()
Debug ""
Debug "Finished"

If Cfgmgr32
  CloseLibrary(Cfgmgr32)
EndIf

Re: Portadresse ausgeben?

Verfasst: 20.02.2010 21:22
von Falko
Vielen Dank DD,

das du dir Gedanken hierzu gemacht hast und
diesen wunderbaren Code hier eingestellt hast.
Es klappt wunderbar in 32-Bit als auch in 64-Bit. :allright:

Grüße, Falko

Re: Portadresse ausgeben?

Verfasst: 11.05.2013 01:18
von Falko
Hallo Daniel,
mit dem aktuellen Windows 8 / 64-Bit und PB 5.11 habe ich folgende Ausgabe:
(Ports) PCI Parallel Port (LPT2)
(Ports) PCI Parallel Port (LPT1)

Finished
Ich weiß, dieser Thread ist schon sehr alt. Aber nun funktioniert mein Programm
unter Windows 8 nicht mehr. Also die LPT-Adresse wird mir nicht mehr angezeigt.

Ich habe nun einiges ausprobiert, komme mit diesem Code leider nicht weiter.

Weißt du noch, wie die Ausgabe sein müsste und ob man noch was ändern könnte?

Nachtrag:
Vorhin, das wurde von PB 5.11 x86 compiliert und nun habe ich mal zum vergleich eine 64-Bit-Version compiliert.
Das sieht dann so aus:
Ports
(Ports) PCI Parallel Port (LPT2) [0000E0F0 - 0000E0F7] [0000E0E0 - 0000E0E7]
Ports
(Ports) PCI Parallel Port (LPT1) [0000E110 - 0000E117] [0000E100 - 0000E107]

Wie man sieht, werden hier die gesuchten Ports ausgegeben. Muss wohl an den neuen Treiber für die MOChip-LPT-Karte liegen.

Finished
Gruß,
Falko

Re: Portadresse ausgeben?

Verfasst: 11.05.2013 08:23
von DarkDragon
Falko hat geschrieben:Wie man sieht, werden hier die gesuchten Ports ausgegeben. Muss wohl an den neuen Treiber für die MOChip-LPT-Karte liegen.
Hat es sich dann damit erledigt? Hab nurnoch auf der Arbeit Windows und dort hab ich kein PB, also kann ich dir diesbezüglich leider nicht helfen.

P.S.: Danke, ich habe meinen Beitrag selbst schon vor längerem gesucht und nicht mehr gefunden :-D .

Re: Portadresse ausgeben?

Verfasst: 11.05.2013 08:33
von Falko
DarkDragon hat geschrieben:Hat es sich dann damit erledigt?
Leider nicht :(. Da ich die LPT-Karte (Treiber für MOSCHIP9835 64-Bit) unter Win8 mit den neusten 64-Bittreiber installieren
musste und das Programm aber auf 32-Bit compiliert werden muss, kriege ich so die gesuchten
Portadressen nicht, die ich sonst immer im Gadget anzeigen konnte, weil diese bedingt kleiner oder gleich Null ist.
Ich vermute mal, dass ich an geeigneter Stellle im Source ein Bitshift anwenden muss. Mal schauen, wie das ging.
DarkDragon hat geschrieben:P.S.: Danke, ich habe meinen Beitrag selbst schon gesucht und nicht mehr gefunden :-D .
Das finde ich einen tollen Zufall :allright:


Gruß,
Falko

Re: Portadresse ausgeben?

Verfasst: 12.05.2013 21:00
von Falko
Okay,
dann kann ich das mit diesem, schönen Code vergessen, welches wohl auf einem
Windows8 / 64-Bit System mit und einer MOSCHIP9815-LPT-Karte und den neusten
Windows 8 - Treibern (64 oder 32Bit installiert) im 32-Bit-Kompilat nicht mehr klar kommt.

Aber trotzdem lieben Dank an DarkDragon für diese tolle Funktion, welche man unter Windows
XP bis Windows 7 wunderbar geholfen hatte automatisch die LPT-Port-Adressen aufzulisten,
die mir in meinem Programm dann zur Auswahl standen.

Vielleicht finde ich dann ja eine andere Möglichkeit die Adressen auszulesen um nicht
nur ein 64-BitProgramm anbieten zu müssen :)

Gruß,
Falko

Re: Portadresse ausgeben?

Verfasst: 15.05.2013 00:09
von Falko
Ich habe nun eine simple Lösung für mich gefunden, damit ich bei mir auf 64 bit testen
kann und wenn das mit Inpout64.dll läuft, dann mit der inpout32.dll für die X86-Rechner
kompiliere. Falls jemand auch dieses Problem mit der Inpout 32/64 und DarkDragons
Programmschnipsel hat, könnte es dann so machen:

Code: Alles auswählen

;- Load Library INPOUTx86
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    If OpenLibrary(0, "inpout32.dll")
      Prototype.i ProtoIOx86_0()                ;kein Parameter
      Global IOx86IsOpen.ProtoIOx86_0 = GetFunction(0, "IsInpOutDriverOpen")
      Prototype.i ProtoIOx86_1(PortAdr.w)         ;1 Parameter
      Global IOx86Inp32.ProtoIOx86_1 = GetFunction(0, "Inp32")
      Prototype.i ProtoIOx86_2(PortAdr.w, WertB.a)  ;2 Parameter
      Global IOx86Out32.ProtoIOx86_2 = GetFunction(0, "Out32") 
    Else
     MessageRequester("Hinweiswarnung","Fehler bei der Initialialisierung von Inpout")
     End
    EndIf
  CompilerEndIf
  
;- Load Library INPOUTx64
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64  
    If OpenLibrary(0, "inpoutx64.dll")
      Prototype.i ProtoIOx86_0()                ;kein Parameter
      Global IOx86IsOpen.ProtoIOx86_0 = GetFunction(0, "IsInpOutDriverOpen")
      Prototype.i ProtoIOx86_1(PortAdr.w)         ;1 Parameter
      Global IOx86Inp32.ProtoIOx86_1 = GetFunction(0, "Inp32")
      Prototype.i ProtoIOx86_2(PortAdr.w, WertB.a)  ;2 Parameter
      Global IOx86Out32.ProtoIOx86_2 = GetFunction(0, "Out32") 
    Else
     MessageRequester("Hinweiswarnung","Fehler bei der Initialialisierung von Inpout")
     End
    EndIf
CompilerEndIf
Hiermit kann man mit dem Debugger auf 64Bit testen und dann, wenn soweit alles funktoniert,
mit 32 Bit für die X86-Rechner die Exe kompilieren.