I am starting to work with WIA 2.0 and, as so many others, have started from the MS provided tutorial & example code (see this http://msdn.microsoft.com/en-us/library/ms629848%28v=VS.85%29.aspx).
Unlike the others what I have been unable to find is where the GUIDs CLSID_WiaDevMgr2 & IID_IWiaDevMgr2 are defined.
My code compiles - the variables are declared in wia_lh.h - but fails to build with error messages that these two symbols are unresolved i.e. not defined.
HRESULT CWiaSP::CreateWiaDeviceManager()
{
pWiaDevMgr = NULL;
HRESULT hr = CoCreateInstance( CLSID_WiaDevMgr2, NULL, CLSCTX_LOCAL_SERVER, IID_IWiaDevMgr2, (void**)&pWiaDevMgr );
return hr;
}
How to identify the GUID value for these: can this be done programmatically, or are they well known values that are defined somewhere?
Related
I'm trying to build a functionality that copies multiple files with default windows dialog.
I found this examples from microsoft: FileOperationSample.cpp
However I get an error on this line:
IShellItemArray *psia;
hr = SHCreateShellItemArray(NULL, psfSampleSrc, c_cMaxFilesToCreate, &rgpidlChildren[0], &psia);
PITEMID_CHILD rgpidlChildren[c_cMaxFilesToCreate] = { 0 };
for (UINT i = 0; SUCCEEDED(hr) && i < ARRAYSIZE(rgpidlChildren); i++)
{
WCHAR szSampleFileName[MAX_PATH];
hr = StringCchPrintfW(szSampleFileName, ARRAYSIZE(szSampleFileName), L"%s%u.%s", c_szSampleFileName, i, c_szSampleFileExt);
if (SUCCEEDED(hr))
{
hr = psfSampleSrc->ParseDisplayName(NULL, NULL, szSampleFileName, NULL, (PIDLIST_RELATIVE *)&rgpidlChildren[i], NULL);
}
}
if (SUCCEEDED(hr))
{
IShellItemArray *psia;
hr = SHCreateShellItemArray(NULL, psfSampleSrc, c_cMaxFilesToCreate, &rgpidlChildren[0], &psia);
The sample code compiles without any errors nor warnings with VS2017. However, if I remove #define STRICT_TYPED_ITEMIDS, I get exactly the same error.
Solution:
Make sure, your source code has #define STRICT_TYPED_ITEMIDS before including any Windows headers, ideally at the beginning of your precompiled header (stdafx.h or pch.h, depending on VS version).
Background:
If STRICT_TYPED_ITEMIDS is not defined, the following defines from the shtypes.h are enabled:
#define PITEMID_CHILD LPITEMIDLIST
#define PCUITEMID_CHILD_ARRAY LPCITEMIDLIST *
So in this case, SHCreateShellItemArray expects a pointer to LPCITEMIDLIST for the 4th parameter, but instead you pass it a pointer to LPITEMIDLIST, which is incompatible with the expected type.
Bonus OldNewThing link:
STRICT_TYPED_ITEMIDS is the shell namespace version of the STRICT macro used by USER and GDI
Yes, samples from Microsoft sometimes need to be adapted to modern headers from modern SDKs. Usually, the more recent SDK (from Visual Studio or not) you use, the stricter the compilation is.
You can just change rgpidlChildren declaration to (note the 'C', for const):
PCITEMID_CHILD rgpidlChildren[c_cMaxFilesToCreate] = { 0 };
After porting a project from visual studio to mingw. I am getting the following linker error
undefined reference to `g_Templates'
undefined reference to `g_cTemplates'
The code which it points to looks something like this
#include <tchar.h>
#endif // DEBUG
#include <strsafe.h>
#include <combase.h>
extern CFactoryTemplate g_Templates[];
extern int g_cTemplates;
HINSTANCE g_hInst;
DWORD g_amPlatform; // VER_PLATFORM_WIN32_WINDOWS etc... (from GetVersionEx)
OSVERSIONINFO g_osInfo;
//
// an instance of this is created by the DLLGetClassObject entrypoint
// it uses the CFactoryTemplate object it is given to support the
// IClassFactory interface
class CClassFactory : public IClassFactory, public CBaseObject
{
private:
const CFactoryTemplate *const m_pTemplate;
...
public:
CClassFactory(const CFactoryTemplate *);
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, __deref_out void ** ppv);
STDMETHODIMP_(ULONG)AddRef();
STDMETHODIMP_(ULONG)Release();
// IClassFactory
STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, __deref_out void **pv);
STDMETHODIMP LockServer(BOOL fLock);
// allow DLLGetClassObject to know about global server lock status
static BOOL IsLocked() {
return (m_cLocked > 0);
};
};
// --- COM entrypoints -----------------------------------------
//
// Call any initialization routines
//
void DllInitClasses(BOOL bLoading)
{
// traverse the array of templates calling the init routine
// if they have one
for (i = 0; i < g_cTemplates; i++) //<---------Cannot recognize this symbol
{
const CFactoryTemplate * pT = &g_Templates[i];
if (pT->m_lpfnInit != NULL)
{
(*pT->m_lpfnInit)(bLoading, pT->m_ClsID);
}
}
}
....
....
I have been searching on this issue for a while and have not made any progress. It seems that that this symbol exists in strmbasd.lib (debug version) and is generated from DirectShow base classes. I generated strmbasd.lib using mingw64 however I am still getting this linker error. I wanted to know if there was any other approach I could try .
I have used Direct Show for Microsoft Visual C++. And found no such issue. Microsoft SDK provides the libraries and headers as well as the base classes. You may want to check the link. I haven't used MingW, so I don't know about the issue of MingW. You may try it in MSVC, MSDN provides some handful informations and references for Direct Show. Please check the previous link mentioned above.
Your including dllentry.cpp/dllsetup.cpp from DirectShow BaseClasses assumes that you develop a filter library and you are expected to define template symbols in your code (example) to satisfy linker.
If you don't see how your code is referencing factories, you can define fake array and g_cTemplates of zero to pass through, however eventually there is something that makes linker drag these symbols into output.
I am trying to register BHO with APPcontainer.Now as per the blog http://blogs.msdn.com/b/ieinternals/archive/2012/03/23/understanding-ie10-enhanced-protected-mode-network-security-addons-cookies-metro-desktop.aspx
,I have defined following in same cpp file as DLLRegister
DEFINE_GUID(CATID_AppContainerCompatible, 0x59fb2056,0xd625,0x48d0,0xa9,0x44,0x1a,0x85,0xb5,0xab,0x26,0x40);
STDAPI DllRegisterServer(void)
{
// let ATL handle this
HRESULT hr = _AtlModule.DllRegisterServer();
ICatRegister* pcr = NULL ;
hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
if (FAILED(hr))
return hr;
if (SUCCEEDED(hr))
{
// Register this category as being "implemented" by
// the class.
CATID rgcatid[1] ;
rgcatid[0] = CATID_AppContainerCompatible;
hr = pcr->RegisterClassImplCategories(CLSID_ABC, 1, rgcatid);
}
When I try to compile this code I am getting following error:
unresolved external symbol CATID_AppContainerCompatible
Not sure why this is coming. I can navigate to CATID_AppContainerCompatible definition by right click on it.
any suggesitons??
I solved the issue. since DEFINE_GUID declares GUID as extern I need to put const GUID CATID_AppContainerCompatible ; in my file .After putting that statement its compiling.
DEFINE_GUID behavior depends on presence of INITGUID definition. This is a very frequent problem, so it makes no sense to repeat the details once again, here is further reading: How to avoid error "LNK2001 unresolved external" by using DEFINE_GUID.
To avoid falling into this trap you can use __declspec(uuid(...)) specifier and let compiler sort GUIDs out automatically, e.g.:
class __declspec(uuid("{26AFA816-359E-4094-90A8-BA73DE0035FA}"))
AppContainerCompatible;
// ...
rgcatid[0] = __uuidof(AppContainerCompatible); //CATID_AppContainerCompatible;
More on this: Referencing GUIDs
I followed this tuorial to create a COM dll in Visual Basic. http://www.codeproject.com/KB/COM/Basics_of_Idl_file.aspx
I now want to use this dll in a C++ project. I used OLE/COM Viewer to create an .idl file as is described in the second half this tutorial.
http://www.codeproject.com/KB/COM/vb_from_vc.aspx
I compiled the .idl with the midl compiler and included the .h file that was created in my c++ project.
Here is my Visual Basic Code
<ComClass(MyComClass.ClassId, MyComClass.InterfaceId, MyComClass.EventsId)> _
Public Class MyComClass
#Region "COM GUIDs"
' These GUIDs provide the COM identity for this class
' and its COM interfaces. If you change them, existing
' clients will no longer be able to access the class.
Public Const ClassId As String = "46604f8a-85a2-4027-9728-0390534c9209"
Public Const InterfaceId As String = "30274029-711d-459a-9270-f9d73ad8737f"
Public Const EventsId As String = "5e234d69-5263-4001-86ff-c475b113a77d"
#End Region
' A creatable COM class must have a Public Sub New()
' with no parameters, otherwise, the class will not be
' registered in the COM registry and cannot be created
' via CreateObject.
Public Sub New()
MyBase.New()
End Sub
Protected Overrides Sub Finalize()
MyBase.Finalize()
End Sub
Public Sub DisplayMessage()
MsgBox("Hello from MyComClass!")
End Sub
End Class
Here is my c++ Code
// Declare an HRESULT and a pointer to the clsVBTestClass interface
HRESULT hr;
_MyComClass *IVBTestClass = NULL;
// Now we will intilize COM
hr = CoInitialize(0);
// Use the SUCCEEDED macro and see if we can get a pointer
// to the interface
if(SUCCEEDED(hr))
{
hr = CoCreateInstance( CLSID_MyComClass,
NULL,
CLSCTX_INPROC_SERVER,
IID__MyComClass,
(void**) &IVBTestClass);
// If we succeeded then call the CountStringLength method,
// if it failed then display an appropriate message to the user.
if(SUCCEEDED(hr))
{
long ReturnValue;
_bstr_t bstrValue("Hello World");
// We can test this HR as well if we wanted to
hr = IVBTestClass->DisplayMessage();
hr = IVBTestClass->Release();
}
else
{
}
}
// Uninitialize COM
CoUninitialize();
I receive the following errors when I compile my c++ project
error LNK2001: unresolved external symbol _CLSID_MyComClass
error LNK2001: unresolved external symbol IID_MyComClass
Could someone help me figure out what I am doing wrong?
If you did not get to the last part of creating a Type Library, that is important.
You then need an #import statement in your C++ code to use the .tlb file (or .dll if the type library is embedded in the dll, which is common).
#import is the equivalent to including a header file with COM, but generates a .tlh file (header) and a .tli (implementation) automatically.
I need to be able to read the target of a shortcut (a .lnk file).
I have Googled this and found numerous results that I have found to be helpful:
http://cboard.cprogramming.com/windows-programming/62962-ishelllink-getpath-dev-cplusplus.html
http://www.go4answers.com/Example/get-shortcut-target-cpp-win64-216615.aspx
http://msdn.microsoft.com/en-us/library/bb776891%28VS.85%29.aspx
http://www.codeproject.com/KB/shell/create_shortcut.aspx
Some of these web pages don't mention which header files I need, and I am unaware how to find this information out.
The code that I am currently trying to get working is this:
#include <windows.h>
#include <string>
#include <objidl.h> /* For IPersistFile */
#include <shlobj.h> /* For IShellLink */
using namespace std;
int main(void)
{
IShellLink* psl;
wchar_t* tempStr = new wchar_t[MAX_PATH];
string path = "E:\\shortcuts\\myshortcut.lnk";
HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*) &psl);
if (SUCCEEDED(hr))
{
IPersistFile* ppf;
hr = psl->QueryInterface( IID_IPersistFile, (LPVOID *) &ppf);
if (SUCCEEDED(hr))
{
hr = ppf->Load(path.c_str(), STGM_READ);
if (SUCCEEDED(hr))
{
WIN32_FIND_DATA wfd;
psl->GetPath(tempStr, MAX_PATH, &wfd, SLGP_UNCPRIORITY | SLGP_RAWPATH);
}
}
}
return 0;
}
You can probably see that this is mainly from one of the websites above, however they did not mention which headers they used, so I had a good guess (which seems to be working) at which ones to use.
Currently the errors I am getting are:
In function 'int main()':
24|error: no matching function for call to 'IPersistFile::Load(const char*, int)'
29|error: no matching function for call to 'IShellLinkA::GetPath(wchar_t*&, int, WIN32_FIND_DATA*, int)'
||=== Build finished: 2 errors, 0 warnings ===|
I was hoping that someone may be able to give me some advice on this, whether it is just pointing me to some better links or, even better, possibly explaining the above code, how to find out which headers to use and where I am going wrong, or an entirely different solution that achieves the same result.
All headers are fine, but you are using wide (wchar_t based) and 'normal' (char based) strings incorrectly: IPersistFile::Load takes a wide string while IShellLinkA::GetPath takes a normal string.
Using this should compile:
IShellLinkA* psl; //specify the ansi version explicitely
CoInitialize( 0 ); //you forgot this, needed for all COM calls to work
char* tempStr = new char[ MAX_PATH ];
std::wstring path = L"E:\\shortcuts\\myshortcut.lnk";
Also if you just want the path, you can just pass 0 instead of a pointer to a WIN32_FIND_DATA.