Get Device Driver INF File API
-
domingo, 11 de marzo de 2012 19:06I seem to recall that there is an API which will return the INF file associated with a device driver but I'm drawing a blank. I want to get the path to the INF File, File Name Section Name and File Date. Could someone please refresh my memory.
Todas las respuestas
-
domingo, 11 de marzo de 2012 19:43
The SP_DRVINFO_DETAIL_DATA structure contains that information. It's returned from a call to SetupDiGetDriverInfoDetail.Armin
- Marcado como respuesta Shanks ZenMicrosoft Contingent Staff, Moderator miércoles, 28 de marzo de 2012 8:36
-
domingo, 11 de marzo de 2012 22:26
Thanks for the assist. I think I got it. Would you be so kind as to take a look at my declare and structure. I had to figure it out the hard way, as I could not find a pinvoke example online. Here are my imports:
<DllImport("SetupAPI.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _ <ReliabilityContract(Consistency.WillNotCorruptState, Cer.None)> _ Public Function SetupDiEnumDeviceInfo(<[In]()> ByVal hDeviceInfoSet As IntPtr, <[In]()> ByVal index As Integer, <Out()> ByRef devInfoData As DeviceInstanceInfo) As <MarshalAs(UnmanagedType.Bool)> Boolean End Function <DllImport("setupapi.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _ <ReliabilityContract(Consistency.WillNotCorruptState, Cer.None)> _ Public Function SetupDiGetDriverInfoDetail(<[In]()> ByVal hDeviceInfoSet As IntPtr, <[In]()> ByVal DeviceInfoData As DeviceDriverInfo, <[In]()> ByVal DriverInfoData As DeviceDriverInfo, <Out()> ByRef DriverInfoDetailData As DeviceDriverInfoDetailData, <[In]()> ByVal DriverInfoDetailDataSize As Int32, <Out()> ByRef RequiredSize As Int32) As Boolean End FunctionHere are my structures:
<StructLayout(LayoutKind.Sequential, Pack:=4, CharSet:=CharSet.Unicode)> _ Public Structure DeviceDriverInfo Public Size As Integer <MarshalAs(UnmanagedType.U4)> _ Public DriverType As DeviceDriverType Public Reserved As IntPtr <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _ Public Description As String <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _ Public Manufacturer As String <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _ Public Provider As String Public ReleaseDate As Long Public Version As Long End Structure <StructLayout(LayoutKind.Sequential, Pack:=4, CharSet:=CharSet.Unicode)> _ Public Structure DeviceDriverInfoDetailData Public cbSize As Int32 Public InfDate As System.Runtime.InteropServices.ComTypes.FILETIME Public CompatIDsOffset As Int32 Public CompatIDsLength As Int32 Public Reserved As IntPtr <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _ Public SectionName As [String] <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _ Public InfFileName As [String] <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _ Public DrvDescription As [String] <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _ Public HardwareID As [String] End Structure
Thanks for the help -
lunes, 12 de marzo de 2012 22:19
I'm sorry for answering late. Just saw your new thread. My problem is that you use different names instead of SP_DRVINFO_DATA etc, so it's a bit hard for me to handle because I always have to find the appropriate types in the SDK first. In addition, I haven't figured out yet how to handle the last member in DeviceDriverInfoDetailData (HardwareID) which has a dynamic length.
I don't make long comments now but post my versions instead. You can see yourself what I've changed: (several things had to be corrected)
Public Const LINE_LEN As UInteger = 256 Public Const MAX_PATH As UInteger = 260 Public Const ANYSIZE_ARRAY As UInteger = 1 <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _ Public Structure SP_DRVINFO_DATA Public Size As UInt32 <MarshalAs(UnmanagedType.U4)> Public DriverType As DeviceDriverType Public Reserved As IntPtr <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> Public Description As String <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> Public Manufacturer As String <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> Public Provider As String Public ReleaseDate As ComTypes.FILETIME Public Version As UInt64 End Structure <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _ Public Structure SP_DRVINFO_DETAIL_DATA Public cbSize As UInt32 Public InfDate As ComTypes.FILETIME Public CompatIDsOffset As UInt32 Public CompatIDsLength As UInt32 Public Reserved As UIntPtr <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=LINE_LEN)> Public SectionName As String <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=MAX_PATH)> Public InfFileName As String <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=LINE_LEN)> Public DrvDescription As String <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=ANYSIZE_ARRAY)> Public HardwareID As String End Structure <StructLayout(LayoutKind.Sequential)> _ Structure SP_DEVINFO_DATA Public cbSize As UInt32 Public ClassGuid As Guid Public DevInst As UInt32 Public Reserved As UIntPtr End Structure Public Declare Auto Function SetupDiEnumDeviceInfo Lib "setupapi.dll" ( _ ByVal hDevInfo As IntPtr, _ ByVal MemberIndex As UInt32, _ <[In](), Out()> ByRef DeviceInfoData As SP_DEVINFO_DATA) _ As Boolean Public Declare Auto Function SetupDiGetDriverInfoDetail Lib "setupapi.dll" ( _ ByVal hDeviceInfoSet As IntPtr, _ <[In]()> ByRef DeviceInfoData As SP_DEVINFO_DATA, _ <[In]()> ByRef DriverInfoData As SP_DRVINFO_DATA, _ <Out()> ByRef DriverInfoDetailData As SP_DRVINFO_DETAIL_DATA, _ ByVal DriverInfoDetailDataSize As Int32, _ ByRef RequiredSize As Int32) As Boolean
- Editado Armin Zingler lunes, 12 de marzo de 2012 22:20
- Marcado como respuesta Shanks ZenMicrosoft Contingent Staff, Moderator miércoles, 28 de marzo de 2012 8:37
-
lunes, 12 de marzo de 2012 22:38
Thanks for your reply and your patience with me. I'm sorry my naming conventions cause problems for you. I do this to try and make the names a little more meaningful for me. I'm not a big fan of C or the notations used. It's all to crypitic for me. VB isn't cryptic and I try to make these things fit into that. In the future I will try to remember to include a notation of the C name of any typedefs I change. I tried as best I could to translate the C code into the correct VB code. I am a bit confused as to how you code the Import when a parameter is in/out. Would that be<[In]()><Out()>? I knew the import wasn't coded quite right and the structure was equally confusing.
Thanks for the help
-
jueves, 15 de marzo de 2012 16:20
Shane,
I already had a library with some native declarations (related to driver installation), but not the ones in question. In addition, I have a managed wrapper for an object-oriented view of the same stuff. That's why I'm currently integrating the missing part in my Dlls before I can test it and finally post a solution. That's why it takes a bit longer, but I'm currently at it.
Armin
-
jueves, 15 de marzo de 2012 16:23Thank you Armin, I appreciate your help with this.
-
jueves, 15 de marzo de 2012 18:18
Currently I'm calling SetupDiEnumDriverInfo. The call works but it always returns False and native error is ERROR_NO_MORE_ITEMS. I've tried it for the device information set and for all devices but I never get driver information. Hmmm.... ...Ok, solved. SetupDiBuildDriverInfoList has to be called before. In case anyone will read this. Oooh, yes, that takes a while to build the list.
...
Now I'm getting ERROR_INVALID_USER_BUFFER at SetupDiEnumDriverInfo. I've verified everything again and again but don't see an error. The structure and the function seem to be correct. Maybe you see something wrong: (turning the tables... ;-) )
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _ Public Structure SP_DRVINFO_DATA Public Size As UInt32 Public DriverType As DriverType Public Reserved As UIntPtr <MarshalAs(UnmanagedType.ByValTStr, sizeconst:=AZ.Win32.Constants.LINE_LEN)> Public Description As String <MarshalAs(UnmanagedType.ByValTStr, sizeconst:=AZ.Win32.Constants.LINE_LEN)> Public MfgName As String <MarshalAs(UnmanagedType.ByValTStr, sizeconst:=AZ.Win32.Constants.LINE_LEN)> Public ProviderName As String Public DriverDate As AZ.Win32.FILETIME 'ComTypes.FILETIME Public DriverVersion As UInt64 End Structure Public Enum DriverType As UInt32 NoDriver = 0 ClassDriver = 1 CompatDriver = 2 End Enum Public Declare Auto Function SetupDiEnumDriverInfo Lib "setupapi.dll" ( _ ByVal DeviceInfoSet As IntPtr, _ ByVal DeviceInfoData As IntPtr, _ ByVal DriverType As DriverType, _ ByVal MemberIndex As UInt32, _ <[In](), Out()> ByRef DriverInfoData As SP_DRVINFO_DATA _ ) As Boolean Public Enum DriverType As UInt32 NoDriver = 0 ClassDriver = 1 CompatDriver = 2 End Enum <StructLayout(LayoutKind.Sequential)> _ Public Structure FILETIME Public LowDateTime As UInteger Public HighDateTime As UInteger End Structure Public Const LINE_LEN As Integer = 256I'm only declare the version of SetupDiEnumDriverInfo here where I pass IntPtr.Zero as the 2nd argument.
The value of the structure size is 1568 at run time on 64 bits here. Should be correct, but obviously it isn't
Armin
- Editado Armin Zingler jueves, 15 de marzo de 2012 18:19
- Editado Armin Zingler jueves, 15 de marzo de 2012 18:20
-
jueves, 15 de marzo de 2012 18:38
Armin
Here are my structures for DeviceDriverInfo:
<StructLayout(LayoutKind.Sequential, Pack:=4, CharSet:=CharSet.Unicode)> _ Public Structure DeviceDriverInfo Public Size As Integer <MarshalAs(UnmanagedType.U4)> _ Public DriverType As DeviceDriverType Public Reserved As IntPtr <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _ Public Description As String <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _ Public Manufacturer As String <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=256)> _ Public Provider As String Public ReleaseDate As Long Public Version As Long End Structure Public Enum DeviceDriverType As Integer Unknown DeviceClass Compatible End Enum
These work fine for me in my program as I am able to return the properties without any problem. I dont have a structure for FileTime. My code manipulates and converts the value directly. Hope this helps you out a bit.
-
jueves, 15 de marzo de 2012 18:54Which value du you get for the Size field (with Marshal.Sizeof)?
Armin
-
jueves, 15 de marzo de 2012 19:04Public Size As Integer is my size variable yours is Public Size As UInt32. Can't see how this would be a problem in your code.
-
jueves, 15 de marzo de 2012 19:21
That's not a value, it's the declaration. ;) My wrong value was 1568, the correct value is 1564.
Meanwhile I figured it out: It works with Pack:=4. The offsets in a 32 bit process are:
without pack:
0000: Size
0004: DriverType
0008: Reserved
0012: Description
0524: MfgName
1036: ProviderName
1548: DriverDate
1560: DriverVersion
with pack = 4
0000: Size
0004: DriverType
0008: Reserved
0012: Description
0524: MfgName
1036: ProviderName
1548: DriverDate
1556: DriverVersion
Obviously, without explicitly specifying pack, pack=8 is used. That's why DriverVersion is aligned at 1560, which is divisible by 8 whereas 1556 is not. However, it's a 32 bit process, so I'm not sure why the marshaller aligns at 8.
Armin
-
jueves, 15 de marzo de 2012 19:41Sorry I misunderstood your question. My processor is 64 Bit. So I should be using Pack 4 right? I'm still trying to understand some of this stuff.
-
jueves, 15 de marzo de 2012 20:38
By default, the default packing alignment is used, which I expect to be 4 in a 32 bit process and 8 in a 64 bit process. But obviously I was wrong. IMO, you do not have to specify the pack value. It should work despite. Though, in this case, it's necessary, yet I don't know why.
I think the sentence in the documentation "Therefore, data fields will start on offsets that are multiples of the requested packing value" is only partially true. Actually two offsets are calculated when aligning a field:
- The next multiple of the pack value- The next multiple of the size of the field to be aligned
The field is aligned to the smaller one of both values.Armin
-
jueves, 15 de marzo de 2012 20:44OK I think I understand what you're saying. I never thought that dealing with unmanaged APIs would be so complicated now I'm starting to understand why the safegards are put in place. I guess even if I don't like dealing with C I'm still dealing with it.
-
jueves, 15 de marzo de 2012 20:45
Example:
<StructLayout(LayoutKind.Sequential, pack:=4)> _ Structure S Public f1 As Byte Public f2 As Long End StructureOffsets are:
00: f1
00: f1
04: f2
Same structure with pack = 8, offsets are:
00: f1
08: f2
That's how I expect it to work - even though not correctly described in the documentation. However, what I'm surprised about is the same structure with pack = 0 (=default) in a 32 bit process:
08: f2
So, pack also seems to be 8 in a 32 bit process. Something learned today...
EDIT: Ok, maybe I got the documentation wrong: "default packing size for the current platform" does not mean at multiples of 4 in a 32 bit process and multiples of 8 in a 64 bit process. Instead it means "only at multiples of the size of the field to be aligned". Can anyone confirm this? (even though it's not the Interop group)
Armin
- Editado Armin Zingler jueves, 15 de marzo de 2012 20:48
- Editado Armin Zingler jueves, 15 de marzo de 2012 20:51
-
viernes, 16 de marzo de 2012 1:18
I think my first message was the answer to the initial question, so I think this thread can be closed. Just trying to keep an overview. I'm gonna answer about SetupDiGetDriverInfoDetail in your other thread: http://social.msdn.microsoft.com/Forums/en-US/vblanguage/thread/43b55963-9d01-441c-a2f2-911ad6ec5b13
Solution is on it's way, but I have to eat, drink, watch football and do other essentail stuff in the meantime, too. :)
Armin
-
viernes, 16 de marzo de 2012 1:25Yeah I understand Armin, I am taking a break too. Eating some pizza and watching some TV, Steven Segal Under Seige with Story Notes. I'm working on getting some of the program output working and displaying the proper information in the meantime. I really appreciate all the help. Thanks so much, it's a pleasure to work with someone who truly wants to help other people and doesn't look down on them just because the don't fully understand a particular concept or idea. Thanks so much.

