ksproxy INF File Basic Question

Discussion in 'Windows Vista Drivers' started by Tom Udale, Oct 17, 2003.

  1. Tom Udale

    Tom Udale Guest

    I have been studying the INF file associated with one of the usbcamd2
    examples (the USBINTEL.INF) and creating a commented version such that I can
    grasp all the details. One bit that is not quite clear yet involves the
    interfaces. Living as I do in the past and being most comfortable with
    device objects/symbolic links rather than device interfaces, it took me a
    while realize what the [.Interfaces] section was actually doing.

    Now that I realize that AddInterface registers the interface(s) supported by
    the KM driver (as opposed to, for example a COM interface which gets
    registered in other ways), I am a bit unclear on what is happening in the
    subsequent AddReg section. The relevant parts of the INF file are:

    [Intel.USBDCam.Interfaces]
    AddInterface=%KSCATEGORY_CAPTURE%,GLOBAL,Intel.USBDCam.Interface
    AddInterface=%KSCATEGORY_VIDEO%,GLOBAL,Intel.USBDCam.Interface

    [Intel.USBDCam.Interface]
    AddReg=Intel.USBDCam.Intf.AddReg

    [Intel.USBDCam.Intf.AddReg]
    HKR,,CLSID,,%ProxyVCap.CLSID%
    HKR,,FriendlyName,,%USB\VID_05D0&PID_FFF4.DeviceDesc%
    HKR,PageAliases,"{71F96464-78F3-11d0-A18C-00A0C9118956}",1,21,E8,C2,3D,
    13,47, d2,11, 0xba, 0x41, 0x0, 0xa0, 0xc9, 0xd, 0x2b, 0x5
    HKR,PinFactory\1\Interfaces\{5BB95400-52BB-11d2-BA41-00A0C90D2B05},,,

    Now for the questions:

    1) A question about interfaces. It is now my understanding that, in
    general, the registry entries specified in [Intel.USBDCam.Intf.AddReg] only
    have meaning in the context of the interface, for example
    KSCATEGORY_CAPTURE. In the context of some other interface, for example
    MY_CUSTOM_INTERFACE, there could be some completely different set of
    registry settings that could be used as needed. Thus, the fact that
    KSCATEGORY_CAPTURE and KSCATEGORY_VIDEO can be registered with the same
    AddReg section indicates that the implementors of those two interfaces chose
    to require the same registry settings. It does not indicate anything
    profound about interfaces in general. Is this correct?

    2) Regardless of the answer to 1, what is the meaning of the listed entries?

    CLSID seems to be set to a GUID defined in ksproxy.h for what reason, I do
    not know. Perhaps to permit multiple implementations of ksproxying? I
    would have thought this was known by the KSCATEGORY_CAPTURE GUID.

    FriendlyName is clear.

    PageAliases is completely unclear. I cannot find any mention of it via
    google or the directx docs. This appears to be the only inf file it exists
    in.

    PinFactory is equally opaque. It exists in several inf files, but with
    different GUIDs.

    Is this something I need to understand or can I just close my eyes and "la,
    la, la....".

    Regards,

    Tom Udale

    PS one last slightly random question. Does an AddReg section always "Device
    Parameters" subtree or is it specific to the top level inf section?
     
    Tom Udale, Oct 17, 2003
    #1
    1. Advertisements

  2. Tom Udale

    Max Paklin Guest

    [Intel.USBDCam.Interfaces]
    These entries are used by system device enumerator. Search for
    CLSID_SystemDeviceEnum and ICreateDevEnum is Platform SDK. I don't remember
    all gory details, but in short you can get a device enumerator for a
    particular category. Specifying the same parameters for two different
    categories is perfectly OK. One app can go and search for devices in
    KSCATEGORY_VIDEO category, while the other app will be doing the same using
    KSCATEGORY_CAPTURE category. One device can expose itself under two
    different categories (and they usually do so) and make itself available to
    all clients.

    What you get from device enumerator is IEnumMoniker. You can use it to
    enumerate all devices registered under given category. When you want to
    create an instance of the device object you call IMoniker::BindToObject.
    Device enumerator will then use CLSID entry to create an object (almost
    always ksproxy) and return that interface to you.
    If you want to get its display name, then FriendlyName is what is used.

    Device enumerator knows nothing about KS proxy. It just happened to be used
    with KS devices, but it can be anything.

    Never heard of this one.
    This could be completely proprietary.
    You can use IMoniker::BindToStorage (it returns IPropertyBag) to get access
    to that area of registry. So during installation you could put whatever data
    you need under that key and then from your own application (or any other
    user land component) check that data using IPropertyBag.

    I've seen it in multiple places, but never used it.
     
    Max Paklin, Oct 17, 2003
    #2
    1. Advertisements

  3. Tom Udale

    Max Paklin Guest

    The information that I am providing here is coming from top of my head. The
    last time I did any digging in this area was 2 years ago. My memory is a bit
    hazy, but I think what I am saying should be not far from the truth.

    Directly or indirectly I don't know. Anyways, it doesn't matter.
    AddInterface does not create or register an interface. It just sets
    parameters for the component that is created through the system device
    enumerator.
    Nothing more, nothing less.

    No, it does not.
    The class driver uses the device or filter descriptor(s) that is (are)
    provided by the minidriver to register and activate interfaces using
    IoRegisterDeviceInterface and IoSetDeviceInterfaceState.

    System device enumerator uses SetupDiXXX functions to enumerate the
    interfaces.
    To create an instance of COM component that facilitate communication with
    the device, system device enumerator uses the stuff added by AddInterface
    section of the INF.

    Did you ever try to look up registry entries you mention here?
    I don't think it works the way you described.

    Yes, you can register regular DShow filter to make it appear under certain
    category. You would use IFilterMapper2::RegisterFilter.
    That's called the "legacy way".

    This key is missing on my machine and I got a lot of devices registered
    under AM_KSCATEGORY_CAPTURE category.

    Interface does not define anything except a category that the device belongs
    to.
    Property/method/event sets define the IOCTLs that are used for communication
    with the driver.

    Use IFilterMapper2::RegisterFilter.
    Of course, no AddInterface is involved.


    -- Max.
     
    Max Paklin, Oct 18, 2003
    #3
  4. Tom Udale

    Tom Udale Guest

    Max,
    I was about to write that I was not convinced by your "No it does not" , but
    as I read about IoRegisterDeviceInterface I now see that it is all a bit
    more nuanced (although I think part of the answer is "Yes it does" :) The
    reason that I was "not convinced" is that the MS documentation is quite
    clear on the function of the AddInterface INF directive. AddInterface
    "...installs device-specific support for device interface classes exported
    to higher level components, such as other drivers or applications."

    See
    http://msdn.microsoft.com/library/d.../en-us/install/hh/install/inf-format_3omq.asp

    They also give you a link to a page that describes device interface classes:
    http://msdn.microsoft.com/library/d...y/en-us/install/hh/install/setup-cls_54kn.asp

    which has a nice introduction:
    http://msdn.microsoft.com/library/d...y/en-us/install/hh/install/setup-cls_8vs7.asp

    In this introduction they explain device interfaces, as I do above, as being
    analagous to device objects and symbolic links: "In Windows NT 4.0 and
    earlier versions of the NT-based operating system, drivers named their
    device objects and then set up symbolic links in the registry between these
    names and a user-visible Win32 logical name. For Windows 2000 and later,
    drivers do not name device objects. Instead, they make use of device
    interface classes."
    So I think the function of AddInterface and the definition of the particular
    "interface" is clear. The question now becomes how does the AddInterface
    INF file directive interact with the IoRegisterDeviceInterface, and
    IoSetDeviceInterfaceState calls that you say are made by the mini-driver
    startup code.

    From my reading of the docs, IoRegisterDeviceInterface provides *exactly*
    the same functionality of the AddInterface directive. Both will register a
    new interface class if the class has not already been registered and both
    will create a new instance of the specified interface for the device in
    question. IoRegisterDeviceInterface also returns the symbolic link that is
    created for the instance of the interface class. This of course is required
    for use in IoSetDeviceInterfaceState to enable the link. Thus the device
    driver must call IoRegisterDeviceInterface and IoSetDeviceInterfaceState in
    its startup code as you already said. That being as it is, it was for a
    moment a little unclear to me why you would use a AddInterface call in your
    inf file. MS says as much in thier documentation for AddInterface:

    "As an alternative to registering its support for a device interface class
    in its INF, a device driver can call IoRegisterDeviceInterface before making
    its initial call to IoSetDeviceInterfaceState. Usually, a PnP function or
    filter driver makes this call from its AddDevice routine."

    I now suspect that it is to "prime the pump", so to speak, for the system
    device enumerator. This is what I think you are getting at when you said:

    "Anyways, it doesn't matter.
    AddInterface does not create or register an interface. It just sets
    parameters for the component that is created through the system device
    enumerator. Nothing more, nothing less."


    AddInterface does in fact register an interface but not because the driver
    is not going to do it later, but rather because there is probably a chicken
    and egg problem such that without the INF file directive, the
    SystemDeviceEnumerator could not find the driver to launch it for the first
    time. Thus you still need the INF AddInterface even though it registers
    exactly the same information as IoRegisterDeviceInterface.

    Lastly, they are completely clear about where this device interface instance
    information is stored in the registry:

    HKLM\System\CurrentControlSet\Control\DeviceClasses\INTERFACE_CLASS_GUID

    This is in fact the case on both my win98me machine and my winxp machine.
    This seems logical to me.
    Ah, I see now that we are saying the same things. This is what I was trying
    to say before when I said:

    "It is my guess that this link is made
    by ksproxy at some point. It sees a KM device that supports
    KSCATEGORY_CAPTURE, and registers itself in
    HKCR\CLSID\AM_KSCATEGORY_CAPTURE. Ksproxy then implements all the usermode
    dshow interfaces by calling down to KM using the ioctrls defined by the
    KSCATEGORY_CAPTURE interface."

    I had the wrong actor, ksproxy vs the SystemDeviceEnumerator, but the result
    is the same. Someone scans the interface list (i.e. that created by
    AddInterface and/or IoRegisterDeviceInterface) and creates a usermode COM
    interface for each KSCATEGORY_CAPTURE device it sees.


    You are right that I had not looked that up as the machine I wrote it from
    did not have any USB cameras on it. The reason I wrote it is because that
    is what MS says in the DShow docs about the registry keys:

    http://msdn.microsoft.com/library/d...tx9_c/directx/htm/layoutoftheregistrykeys.asp

    They are pretty clear that the COM dll server for the filter is registered
    in HKCR/CLSID/FILTER_GUID and that this filter is attached to a filter
    category (i.e. AM_KSCATEGORY_CAPTURE) via
    HKCR/CLSID/FILTER_CATEGORY_GUID/Instance/FILTER_GUID.

    On the latter point, either they lied or, more likely, this is simply not
    the case for kxproxy'ed cameras. There is no
    HKCR/CLSID/AM_KSCATEGORY_CAPTURE branch on either my XP or 98ME machine.

    Since both you and I do not have this key, the only answer I can come up
    with is that the SystemDeviceEnumerator both scans this key for "legacy
    filters" (as you name them below) and it also scans the device interface
    list for devices that support known device interface classes such as
    KSCATEGORY_CAPTURE. In the latter case, there must then be some secondary
    level of redirection that launches ksproxy that I have not discovered yet.
    I say this because I assume that it is possible to write usermode COM
    component to proxy a usbcamd based mini-driver in a completely custom manner
    rather than using ksproxy (not that you would want to do that).
    That makes sense. I suspect then that this must be what gets put into
    HKCR/CLSID/FILTER_CATEGORY_GUID/Instance that the MS docs keep talking
    about.
    Well it does define the private IOCTLs used by the usbcamd framework to
    handle all the various communications between ksproxy and usbcamd right?
    Meaning, if you were to try and write a driver completely from scratch that
    did not use usbcamd but functioned seamlessly with ksproxy, you would need
    to understand those private IOCTLs which all drivers supporting the
    KSCATEGORY_CAPTURE interface must support.

    This is for communication above and beyond that directly defined by
    KSCATEGORY_CAPTURE (i.e. custom extensions) right?

    Thanks again for your help Max, this is making alot more sense.

    Regards,

    Tom
     
    Tom Udale, Oct 20, 2003
    #4
  5. Tom Udale

    Max Paklin Guest

    Tom,
    http://msdn.microsoft.com/library/d.../en-us/install/hh/install/inf-format_3omq.asp

    Wow! You opened up my eyes. Thanks!
    Indeed this can be done the way you described. I think you missed one point
    though. AddInterfaces can tell that the device in question will expose
    particular interface. However to make actually happen the interface in
    question must be registered with [InterfaceInstall32] section in INF file
    (or be publicly registered already). On top of that you have to activate the
    interface by calling IoSetDeviceInterfaceState. Now the question I have why
    would you want to go through all that trouble with registering an interface
    from INF if you still have to activate it programmatically with
    IoSetDeviceInterfaceState? It's much easier to just call
    IoRegisterDeviceInterface and be done with it.

    FYI: none of INFs under $(Windows)\INF has [InterfaceInstall32] section.

    a

    Yes, you right.

    I don't think that this is why they did that (for the sake of this
    discussion I put SWENUM and ROOT based devices aside).
    For regular driver a device object is already created, an interface is
    registered and there is no chicken and egg problem.

    This is how I think the whole thing works:
    1. the driver is installed and AddInterface is executed _loading parameters
    (CLSID and such) in registry_.
    2. the driver loads and registers an interface.
    3. upon the request from an app the device enumerator uses SetupDiXXX to
    find the device exposing certain interface.
    4. the device enumerator creates IMoniker object and gives its symbolic name
    same as FriendlyName data in registry under corresponding interface location
    (the location is retrieved using SetupDiXXX).
    5. the app checks the device name using IMoniker::GetDisplayName and picks
    up the device for graph creation.
    6. the app then uses IMoniker::BindToObject to create an instance.
    7. the device enumerator's IMoniker::BindToObject gets the CLSID entry from
    the same place in registry and does CoCreateInstance on that CLSID
    (typically ksproxy).
    8. it then passes the information about the device to ksproxy through some
    private interface.

    So in a way they use AddInterfaces as a mechanism to specify CLSID and
    FriendlyName (plus other parameters) so that device enumerator can do its
    job.

    I think the documentation is incorrect.
    These data can be found under
    HKCR/CLSID/{083863F1-70DE-11d0-BD40-00A0C911CE86}/Instance/{FILTER GUID}.
    {083863F1-70DE-11d0-BD40-00A0C911CE86} is the GUID for system device
    enumerator. The information gets there by using IFilterMapper2::Register.
    But then again, this only applies to regular DShow filters. The devices that
    are exposed trough ksproxy won't be present in that list.

    Basically, this list is there to augment the devices represented by ksproxy
    and give a chance to regular DShow filter to be expose in the same way as
    ksproxy-like devices do.

    For device emulation purposes I once wrote a regular DShow filter that
    behaved exactly like analog TV tuner does (exposed IAMTVTuner and friends).

    The devices that fall under certain category are "expected" to support
    certain property (method or event) sets. It does not mean that they have to.
    It is just that most of the clients will expect the device under
    KSCATEGORY_CAPTURE to support the property set that lets them tweak
    brightness, contrast and saturation, for example. It does not mean that you
    can't write the driver that falls under "capture" category and does not
    support that particular property set. You could. Just be prepared to see
    some applications having trouble detecting/using your device.


    -- Max.
     
    Max Paklin, Oct 20, 2003
    #5
  6. Tom Udale

    Tom Udale Guest

    Max,
    I actually got that point (although that fact may have been obscured in my
    lengthy reply). I think the thing is that in all the examples I have seen,
    the interface is question is always a MS defined one and thus no
    [InterfaceInstall32] is needed.
    Right, I am wondering the same thing. Of course, without the
    [InterfaceInstall32] it is not that big a deal, but still it is kind of
    annoying to do the AddInteface bit. The thing is, it is done that way in a
    whole pile of INF files I have seen (for example the USBINTEL.INF) so I
    figured there must be a reason. That is why I was speculating that it had
    something to do with the very first time the driver was loaded; that if the
    information was not there from the INF file, the SystemDeviceEnumerator
    would not be able to find it. Since you don't seem to think that is an
    issue, I cannot think of why you would do it.

    Actually, I guess another possiblity would be that you really needed to
    preload the registry with some specific data such as they did in the
    USBINTEL.INF example (look back to my first post in the thread).

    Trying to sort out the [Intel.USBDCam.Intf.AddReg] stuff was why I started
    this whole thread. I take it then from this whole discussion that the stuff
    in [Intel.USBDCam.Intf.AddReg] is simply something that is needed only by
    the intel camera and not something that is part of the larger world of
    DShow.
    Right. I suspect that is because they are all using standard interfaces.
    Is that true even of devices that are not present at boot time but are
    plugged in later (for example USB cameras). It is possible that when you
    plug the camera in for the first time the system might need this interface
    information before the driver entry is called?

    Ok, I am with you. Here the registration that the driver does would
    replicate what happened in step 1.
    This all makes complete sense.
    Right! That must be it. Without the AddInterface, there is no way to get
    the friendly name. For a device that you were not planning on making public
    (i.e. one that would show up in graph edit) there is no need for the
    friendly name so I suspect you could drop the AddInterface. Or, as I said
    above, you may also want the registry pre-populated with some settings. In
    this case, even if the device was not intended to show up in any lists, you
    would still want to do a AddInterface.
    Ah, thanks.
    friends).
    Right. So that is possible.

    Yes, but what I was getting at is that KSCATEGORY_CAPTURE, as a *device
    interface class*, defines a set of IOCTRL that *must* be answered by the
    device. As I read the header files, I see that these IOCTRLs are
    IOCTL_KS_DISABLE_EVENT, IOCTL_KS_ENABLE_EVENT, IOCTL_KS_METHOD,
    IOCTL_KS_PROPERTY, etc. Any driver that claims to support the
    KSCATEGORY_CAPTURE device interface must not only recognize those IOCTRLs
    but reply as expected to them. One does not normally think of things this
    way because ksproxy and the usbcamd (or its analogs) handle all these IOCTLs
    and pass down higher level concepts to the minidriver (Property Sets, etc).
    However, I strongly suspect that if you wrote a driver from scratch that did
    a IoRegisterDeviceInterface(KSCATEGORY_CAPTURE) but did not reply to
    IOCTL_KS_DISABLE_EVENT as expected you would be in alot of trouble as far as
    Dshow was concerned.

    Actually now that I look at the docs for IOCTL_KS_*
    (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/stream/hh/
    stream/ksfunc_7sqb.asp), they have things named pretty sensibly. The
    microsoft component you bind your mini-driver to is the class driver; i.e.
    the driver that implements the expected behavior for the device interface
    class. As they say: "Microsoft does not recommend bypassing the class
    driver level by writing a driver directly under KS 1.0 services. However, if
    a vendor implemented a driver in this way, the driver would need to handle
    the IOCTL_KS_* control codes."

    This does bring me to another question though. I see that all the
    IOCTL_KS_* commands are defined as CTL_CODE(FILE_DEVICE_KS, ,,,). Thus MS
    has created a completely new device type, FILE_DEVICE_KS, for these IOCTLS.
    Does this imply if I wanted to send a pile of custom IOCTLs to the device, I
    could simple define them as CTL_CODE(32768,,,,) like I do for any other
    non-standard device and use the handle I get from KsGetObjectHandle and call
    DeviceIOCtrl on it and still not interfere with the operation of kxproxy
    talking to the class driver?

    Regards,

    Tom
     
    Tom Udale, Oct 20, 2003
    #6
  7. Tom Udale

    Max Paklin Guest

    I don't think that this is why they did that (for the sake of this
    Again, I am not 100% sure about this, but I believe that the information in
    registry is used by device enumerator to get parameters like CLSID and
    FriendlyName. Why would you need those parameters for device that has no
    driver loaded for it? This is something that can popup in the future (when
    device has the driver installed), but currently there is no way the user can
    make use of that information.

    This is not really a replication. A replication just happens to be a side
    effect. The goal is to stick those CLSID (and other) parameters into
    registry.

    You could do pre-population, but I don't think that's the goal. Simply
    because I don't see a reason for that (do you?) and at the same time there
    seems to be no other way to set those CLSID parameters needed by device
    enumerator.
    So this is just the necessary evil.

    There is no way you can avoid supporting above meantioned IOCTLs.
    Those are supported automatically by the class driver for you. You don't
    have to do anything.

    IOCTLs

    It is not usbcamd. It is stream class driver that handles those.
    As long as you write a minidriver for stream class or AVStream you'll get
    those IOCTLs for granted.

    You don't need to do all this. I don't think it will work the way you
    describe although I never tried.
    The class driver takes over IOCTLs completely. I would expect it to reject
    any IOCTL that it does not know (of course, you can hook its dispatch entry
    point and do what you want, but why would you?).

    To set or get custom properties what you do is
    1. define your own GUID for the property set
    2. expose the property set with above meantioned GUID and define property
    items describing your property set.
    3. QI ksproxy for IKsPropertySet and use it to get or set properties for
    your set.
    Internally ksproxy and the class driver would use same old IOCTL with
    IOCTL_KS_... to communiate with your minidriver, but you really don't have
    to care about all details.

    -- Max.
     
    Max Paklin, Oct 20, 2003
    #7
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.