Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: how to make this compile IID_PPV_ARGS(&pServiceManager)


This question is not answered.


Permlink Replies: 5 - Last Post: Nov 11, 2016 5:36 PM Last Post By: Remy Lebeau (Te... Threads: [ Previous | Next ]
Asger Joergensen

Posts: 370
Registered: 11/18/08
how to make this compile IID_PPV_ARGS(&pServiceManager)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 11, 2016 10:25 AM
Hi

Almost all the COM code I find on msdn contains:
IID_PPV_ARGS( &pServiceManager ) 

or similar code and every time I get a compilor error of this kind:
[BCC32 Error] Unit1.cpp(70): E2496 Invalid call to uuidof(struct type | variable)

I know I can replace it with:
IID_IPortableDeviceServiceManager ,(LPVOID*)&pServiceManager );

but it is often very difficult to find those IID's and in this last case I simply cant find the IID
IID_IPortableDeviceServiceManager

Anybody who knows how to make the macro compile or second best have the definition for the IID

I'm Using CB2009 on Win7 64bit.

Thanks in advance
Best regards
Asger
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: how to make this compile IID_PPV_ARGS(&pServiceManager)
Helpful
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 11, 2016 11:04 AM   in response to: Asger Joergensen in response to: Asger Joergensen
Asger wrote:

Almost all the COM code I find on msdn contains:

IID_PPV_ARGS( &pServiceManager )


or similar code

IID_PPV_ARGS() is provided as a convenience and a safety catch, but it is
not strictly required.

and every time I get a compilor error of this kind:

[BCC32 Error] Unit1.cpp(70): E2496 Invalid call to uuidof(struct type | </div>
variable)
<div class="jive-quote">

That means pServiceManager is not an interface type that has been marked
with __declspec(uuid("the iid here")):

http://docwiki.embarcadero.com/RADStudio/en/Declspec(uuid(%22ComObjectGUID%22))

I know I can replace it with:

IID_IPortableDeviceServiceManager ,(LPVOID*)&pServiceManager );


but it is often very difficult to find those IID's

Not really. They are always named the same as their cooresponding interface
type, and they are always declared in the same header file as the interface
type.

in this last case I simply cant find the IID
IID_IPortableDeviceServiceManager

IPortableDeviceServiceManager and IID_IPortableDeviceServiceManager are declared
in PortableDeviceAPI.h (per its documentation).

However, the version of PortableDevieAPI.h that is included in C++Builder
2009 does not declare IPortableDeviceServiceManager (and thus IID_IPortableDeviceServiceManager).
It was added in C++Builder 2010. So, if you want to use IPortableDeviceServiceManager
in your C++Builder 2009 project, you will have to declare IPortableDeviceServiceManager
manually in your own code, eg:

static const IID IID_IPortableDeviceServiceManager = {0xa8abc4e9, 0xa84a, 
0x47a9, {0x80, 0xb3, 0xc5, 0xd9, 0xb1, 0x72, 0xa9, 0x61}};
 
MIDL_INTERFACE("a8abc4e9-a84a-47a9-80b3-c5d9b172a961")
IPortableDeviceServiceManager : public IUnknown
{
public:
    virtual HRESULT STDMETHODCALLTYPE GetDeviceServices( 
        LPCWSTR pszPnPDeviceID,
        REFGUID guidServiceCategory,
        LPWSTR *pServices,
        DWORD *pcServices) = 0;
        
    virtual HRESULT STDMETHODCALLTYPE GetDeviceForService( 
        LPCWSTR pszPnPServiceID,
        LPWSTR *ppszPnPDeviceID) = 0;
};


--
Remy Lebeau (TeamB)
Asger Joergensen

Posts: 370
Registered: 11/18/08
Re: how to make this compile IID_PPV_ARGS(&pServiceManager)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 11, 2016 2:55 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
HI Remy

Remy Lebeau (TeamB) wrote:

but it is often very difficult to find those IID's

Not really. They are always named the same as their cooresponding interface
type, and they are always declared in the same header file as the interface
type.

Yes I know and that's the easy part

static const IID IID_IPortableDeviceServiceManager = {0xa8abc4e9, 0xa84a, 
0x47a9, {0x80, 0xb3, 0xc5, 0xd9, 0xb1, 0x72, 0xa9, 0x61}};

It is this part with the hex, that is hard to find.

So, I thank you, so very much for that code, now my code is beginning to work. :-)

That means pServiceManager is not an interface type that has been marked
with __declspec(uuid("the iid here")):
struct __declspec(uuid("{a8abc4e9-a84a-47a9-80b3-c5d9b172a961}")) IID_IPortableDeviceServiceManager; //compiles
 
IPortableDeviceServiceManager*  pServiceManager;
hr = pPortableDeviceManager->QueryInterface( IID_PPV_ARGS( &pServiceManager ) ); //gives error
 

[BCC32 Error] Unit1.cpp(75): E2496 Invalid call to uuidof(struct type | variable)

p.s. I have no GUID string for IPortableDeviceServiceManager anywhere on my system,
unless it is the same as for IID_IPortableDeviceServiceManager

Thanks again
Best regards
Asger

Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: how to make this compile IID_PPV_ARGS(&pServiceManager)
Correct
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 11, 2016 3:26 PM   in response to: Asger Joergensen in response to: Asger Joergensen
Asger wrote:

It is this part with the hex, that is hard to find.

Not if you have up-to-date header files.

struct __declspec(uuid("{a8abc4e9-a84a-47a9-80b3-c5d9b172a961}"))
IID_IPortableDeviceServiceManager; //compiles

It may compile, but it is wrong. Don't apply __declspec(uuid) to the IID
variable declaration. Apply it to the interface type declaration instead.
In the example I gave you earlier:

MIDL_INTERFACE("a8abc4e9-a84a-47a9-80b3-c5d9b172a961")
IPortableDeviceServiceManager : public IUnknown
{
...
};


MIDL_INTERFACE is a macro that translates to this:

struct __declspec(uuid("a8abc4e9-a84a-47a9-80b3-c5d9b172a961")) __declspec(novtable)
IPortableDeviceServiceManager : public IUnknown
{
...
};


IPortableDeviceServiceManager* pServiceManager;
hr = pPortableDeviceManager->QueryInterface( IID_PPV_ARGS( &pServiceManager
) ); //gives error

[BCC32 Error] Unit1.cpp(75): E2496 Invalid call to uuidof(struct type |
variable)

Because you have not applied __declspec(uuid) to the IPortableDeviceServiceManager
interface type. IID_PPV_ARGS() calls __uuidof() on the type of the variable
that is passed to it. The above query statement roughly translates to the
following:

hr = pPortableDeviceManager->QueryInterface(__uuidof(*pServiceManager), (void**)&pServiceManager);


AKA

hr = pPortableDeviceManager->QueryInterface(__uuidof(IPortableDeviceServiceManager), 
(void**)&pServiceManager);


p.s. I have no GUID string for IPortableDeviceServiceManager
anywhere on my system

Yes, because again, as I told you earlier: "the version of PortableDevieAPI.h
that is included in C++Builder 2009 DOES NOT DECLARE IPortableDeviceServiceManager
(and thus IID_IPortableDeviceServiceManager). It was added in C++Builder
2010."

unless it is the same as for IID_IPortableDeviceServiceManager

Yes, the guid used in __declspec(uuid) on the IPortableDeviceServiceManager
interface is the same guid used for IID_IPortableDeviceServiceManager. That
is the key that lets the __uuidof() trick work at all.

--
Remy Lebeau (TeamB)
Asger Joergensen

Posts: 370
Registered: 11/18/08
Re: how to make this compile IID_PPV_ARGS(&pServiceManager)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 11, 2016 3:58 PM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Hi Remy

Thanks for taking the time, I'm slowly getting it, I think.:-)

Remy Lebeau (TeamB) wrote:

Yes, because again, as I told you earlier: "the version of PortableDevieAPI.h
that is included in C++Builder 2009 DOES NOT DECLARE IPortableDeviceServiceManager
(and thus IID_IPortableDeviceServiceManager). It was added in C++Builder
2010."

I have a newer header, I found on the web, it contains the example you posted, but because I
wasn't aware that the GUID and the IID string was the same and because I still got the error:

E2496 Invalid call to uuidof(struct type | variable)

I asked for the IID.
I have it working now, thanks to you, so I'm just trying to understand what is going on.

hr = pPortableDeviceManager->QueryInterface( IID_PPV_ARGS( &pServiceManager ) );
hr = pPortableDeviceManager->QueryInterface( __uuidof(*pServiceManager), (void**)&pServiceManager ));

both gives the error (yes I know they are the same ), but this one works:
hr = pPortableDeviceManager->QueryInterface( __uuidof(IPortableDeviceServiceManager), (void**)&pServiceManager );


Thanks again
Best regards
Asger
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: how to make this compile IID_PPV_ARGS(&pServiceManager)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Nov 11, 2016 5:36 PM   in response to: Asger Joergensen in response to: Asger Joergensen
Asger wrote:

 
hr = pPortableDeviceManager->QueryInterface( IID_PPV_ARGS( &pServiceManager </div>
) );
<div class="jive-quote"> 
hr = pPortableDeviceManager->QueryInterface( __uuidof(*pServiceManager), </div>
(void**)&pServiceManager ));
<div class="jive-quote"> 


both gives the error (yes I know they are the same ), but this one
works:

 
hr = pPortableDeviceManager->QueryInterface( __uuidof(IPortableDeviceServiceManager), </div>
(void**)&pServiceManager );
<div class="jive-quote"> 

In theory, there should be no difference between using __uuidof(*pServiceManager)
and __uuidof(IPortableDeviceServiceManager), since __uuidof() is evaluated
at compile-time, and should be able to deduce the correct type from the input,
similar to how sizeof() does. But in practice, apparently Embarcadero's
compilers require an input type only, not a variable. In fact, in C++Builder
2010 and later, IID_PPV_ARGS() uses a helper template function to extract
the type from the variable and then pass the type to __uuidof():

extern "C++"
{
#if defined(__CODEGEARC__) && defined(__clang__)
    struct IUnknown;
#endif
 
    template<typename T> void** IID_PPV_ARGS_Helper(T** pp) 
    {
        static_cast<IUnknown*>(*pp);    // make sure everyone derives from 
IUnknown
        return reinterpret_cast<void**>(pp);
    }
#if defined(__CODEGEARC__)
    template<typename T> const GUID& _CG_GUID_PPT_Helper(T**) 
    {
      return __uuidof(T);
    }
#endif
}
 
#if defined(__CODEGEARC__)
#define IID_PPV_ARGS(ppType) _CG_GUID_PPT_Helper(ppType), IID_PPV_ARGS_Helper(ppType)
#else
#define IID_PPV_ARGS(ppType) __uuidof(**(ppType)), IID_PPV_ARGS_Helper(ppType)
#endif
#else


In C++Builder 2009, IID_PPV_ARGS() does not use that extra helper:

extern "C++"
{
    template<typename T> void** IID_PPV_ARGS_Helper(T** pp) 
    {
        // make sure everyone derives from IUnknown
        static_cast<IUnknown*>(*pp);
        
        return reinterpret_cast<void**>(pp);
    }
}
 
#define IID_PPV_ARGS(ppType) __uuidof(**(ppType)), IID_PPV_ARGS_Helper(ppType)


--
Remy Lebeau (TeamB)
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02