3
votes

Quick info: I am using Visual Studio 2008, Windows 8 (64-bit).

I am trying to creating an AutoPlay Handler that presents itself when a WPD device is plugged into the computer. If my AutoPlay option is selected, all I want it to do is to simply launch my application.

Since there aren't any recent examples of implementing AutoPlay for Windows, I was hoping someone could help me out a little and answer a couple of questions:

1). I have created an ATL project with a COM object that implements the IHWEventHandler interface. Initially, all I am trying to get the COM object to do is to create a .txt file in my C drive to indicate that it was called successfully. I have tried getting my AutoPlay event to point to this COM object, but nothing happens when I select my AutoPlay entry. Here is my .h code for my COM class:

    class ATL_NO_VTABLE CSimpleAutoPlayCom :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CSimpleAutoPlayCom, &CLSID_SimpleAutoPlayCom>,
    public IHWEventHandler
    //public ISimpleAutoPlayCom
    {
    public:
    CSimpleAutoPlayCom()
    {
        ofstream myfile;
        myfile.open ("C:\\AutoPlayExerciseWorked.txt");
        myfile << "Called from Constructor.\n";
        myfile.close();
    }

    DECLARE_REGISTRY_RESOURCEID(IDR_SIMPLEAUTOPLAYCOM)

    DECLARE_NOT_AGGREGATABLE(CSimpleAutoPlayCom)

    BEGIN_COM_MAP(CSimpleAutoPlayCom)
    //COM_INTERFACE_ENTRY(ISimpleAutoPlayCom)
    COM_INTERFACE_ENTRY(IHWEventHandler)
    END_COM_MAP()
    DECLARE_PROTECT_FINAL_CONSTRUCT()

    HRESULT FinalConstruct()
    {
        return S_OK;
    }

    void FinalRelease()
    {
    }

    public:
    // IHWEventHandler
    STDMETHODIMP Initialize(__RPC__in LPCWSTR pszParams);
    STDMETHODIMP HandleEvent(__RPC__in LPCWSTR pszDeviceID, __RPC__in LPCWSTR              pszAltDeviceID, __RPC__in LPCWSTR pszEventType);
    STDMETHODIMP HandleEventWithContent(__RPC__in LPCWSTR pszDeviceID, __RPC__in LPCWSTR pszAltDeviceID, __RPC__in LPCWSTR pszEventType, __RPC__in LPCWSTR pszContentTypeHandler, __RPC__in_opt IDataObject *pdataobject);

    };

This is the .cpp:

// CSimpleAutoPlayCom
STDMETHODIMP CSimpleAutoPlayCom::Initialize(__RPC__in LPCWSTR pszParams)
{
    ofstream myfile;
    myfile.open ("C:\\AutoPlayExerciseWorked.txt");
    myfile << "Called from Initialize\n";
    myfile.close();
    return S_OK;
}

STDMETHODIMP CSimpleAutoPlayCom::HandleEvent(__RPC__in LPCWSTR pszDeviceID, __RPC__in LPCWSTR pszAltDeviceID, __RPC__in LPCWSTR pszEventType)
{
    ofstream myfile;
    myfile.open ("C:\\AutoPlayExerciseWorked.txt");
    myfile << "Called from HandleEvent.\n";
    myfile.close();
    return S_OK;
}

STDMETHODIMP CSimpleAutoPlayCom::HandleEventWithContent(__RPC__in LPCWSTR pszDeviceID, __RPC__in LPCWSTR pszAltDeviceID, __RPC__in LPCWSTR pszEventType, __RPC__in LPCWSTR pszContentTypeHandler, __RPC__in_opt IDataObject *pdataobject)
{
    ofstream myfile;
    myfile.open ("C:\\AutoPlayExerciseWorked.txt");
    myfile << "Called from HandleEventWithContent.\n";
    myfile.close();
    return S_OK;
}

Overall, does this implementation look correct? Do I need to implement any additional interface in order to get my AutoPlay event to call this COM object?

I understand that when i build the project, Visual Studio automatically registers my COM object. I build my COM object for 64-bit windows, and register the .dll using regsvr32.exe as well, but this does not seem to help.

2). Also, I am suspecting that perhaps I did not register my AutoPlay registry keys correctly. I first manually added my Autoplay event handler like so:

HKEY_LOCAL_MACHINE > SOFTWARE > Microsoft > Windows > CurrentVersion > Explorer > AutoPlayHandlers > Handlers > MyAutoPlayHandler

MyAutoPlayHandler holds the following:

Action REG_SZ MyAction

DefaultIcon REG_SZ (directory to my application icon)

InvokeProgID REG_SZ (name of key under HKEY_CLASSES_ROOT that was generated by my ATL project: AutoPlayExericesCom.SimpleAutoPlayCom.1)

InvokeVerb REG_SZ open

Provider REG_SZ Myself

Then I added MyAutoPlayHandler to the following:

HKEY_LOCAL_MACHINE > SOFTWARE > Microsoft > Windows > CurrentVersion > Explorer > AutoPlayHandlers > EventHandlers > WPD > Function > {2D8A6512-A74C-448E-BA8A-F4AC07C49399} which is WPD_FUNCTIONAL_CATEGORY_ALL

Cool, so I plug in my Android device, and I see my AutoPlay entry in the AutoPlay list. I click it, and nothing happens (no txt file was created in the C drive as I was expecting).

So I Additionally create another key like the following:

HKEY_CLASSES_ROOT > MyAutoPlayDropHandler > shell > open > DropTarget

Where DropTarget Contains a CLSID value with the CLSID idea of the COM object I created. I change the InvokeProgID to point to this key, but still nothing happens.

For experimentation, I tried adding my handler under the ShowPicturesOnArrival key, and when plugging in a USB drive containing images, then selecting my AutoPlay Entry, I got the following error message:

"This file does not have a program associated with it to perform this action. Please install a program or, if on is already installed, create an association in the Default Programs control panel."

So now I have some kind of error response to the ShowPicturesOnArrival key, but why nothing for the WPD? I'm suspecting I'm missing something somewhere to get this to work, but I am running out of ideas. Any suggestions that I could try to fix this would be greatly appreciated.

1
I have edited the post to make it less generic.user2136288
So are you writing this application in C# or C++ because you posted C++ code.Security Hound
With my current attempt, I'm writing this in c++.user2136288

1 Answers

0
votes

I know this has been a while, but for anyone else who finds this post I solved this issue that I was also having by copying how VLC does AutoPlay Events. It doesn't allow you to call running code, but it will at least allow you to call your application with whatever command line arguments you wish.

Just add the following registry keys to your machine, replacing VLC with your app.

HKEY_CLASSES_ROOT 
   VLC
       shell 
          import 
             Open
                command 
                   Default = "[Path]\vlc.exe" --started-from-file dvd:///%1

HKEY_LOCAL_MACHINE 
   SOFTWARE 
      Microsoft 
         Windows 
            CurrentVersion 
               Explorer 
                  AutoplayHandlers 
                     EventHandlers
                        PlayDVDMovieOnArrival
                           VLCPlayDVDMovieOnArrival [REG_SZ]
                     Handlers 
                        VLCPlayDVDMovieOnArrival 
                           Action [REG_SZ]= Play DVD Movie
                           DefaultIcon [REG_EXPAND_SZ]= [somepath]\VLC.exe, 0 
                           InvokeProgID [REG_SZ]= VLC.DVDMovie
                           InvokeVerb [REG_SZ]= Open
                           Provider [REG_SZ]= VideoLanVLC media player