I Implemented file dropping based on a drop target class sample from catch22.net. Everything works fine on 32-Bit - but nothing works in my x64-Bit version.
HRESULT __stdcall CDropTarget::QueryInterface (REFIID iid, void ** ppvObject)
is not called when calling
pDropTarget = new CDropTarget(hwnd);
CoLockObjectExternal(myDropTarget, TRUE, FALSE);
as it is in the 32-Bit version. The problem occurs on XP and Windows 7. I am using VS 2010.
Whats the problem?
Related
These days I upgrade to Windows 10 to 1903, however, after that, my MFC program soon disappears after running up. The solution is composed of an MFC project and a DLL project, they are static linked.
Thank you all for paying attention to my question. So far the issue disappear, and below is the story.
1) I modified my code to dynamic link.
2) I got the message of System AccessViolationException when calling the second API of DLL.
3) I found think link. Programs randomly getting System.AccessViolationException
4) In the post, someone mentioned that change platform setting may solve it
5) So I change my platform setting to x64
6) It works
7) I continue to finish my work base on x64 and everything looks OK
8) However I was required to provide x32 version Orz
9) So I have to dig this question as very first priority
10) However, base on the modified source code, now x32 is able to run
Sorry there is not so many useful information.....
There is more information.
I tried to install VS2013 Express at another Win7 64bit PC, which is able to re-produce the phenomenon. It does not matter x86 or Win32 this time.
When Running "Local Windows Debugger," (or use hostkey of: F10, F11, F5)
the debug interface soon finish, with below log:
The program '[2576] test.exe: Native' has exited with code 1 (0x1).
However, in my code did not write any pattern like "return 1"
Below is the main function built-in
[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
// Enabling Windows XP visual effects before any controls are created
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
// Create the main window and run it
Application::Run(gcnew Form_main());
return 0;
}
I'll try to be brief: We have code written in Visual Basic 6.0 that I am trying to compile on a Windows 7 64-bit computer. (Previously this was compiled on an old XP computer.) Most of the code seems to compile correctly, however certain code that has Attributes, like the NewEnum, are not honoring the VB attribute. Here is an example:
The VB6 method looks like this:
Public Property Get NewEnum() As IUnknown
Attribute NewEnum.VB_UserMemId = -4
Attribute NewEnum.VB_MemberFlags = "40"
'this property allows you to enumerate
'this collection with the For...Each syntax
Set NewEnum = mCol.[_NewEnum]
End Property
This is default Enumerator that is created when you use the Class Builder Utility.
However, the Attribute elements are not honored when the code is compiled. Using the OLE View program, it shows that the Attributes are ignored.
The XP computer produces the following snippet:
[id(0xfffffffc), propget, hidden]
HRESULT NewEnum([out, retval] IUnknown** );
But the Windows 7 computer generates:
[id(0x68030000), propget]
HRESULT NewEnum([out, retval] IUnknown** );
I have attempted to set the Visual Basic application to run in XP (Service Pack 3) Compatibility mode and this has not helped.
Because of the size and complexity of our application we cannot port it from VB6 to .NET at this time, and we need to get it to compile. Does anyone know how to properly configure VB6 so that it will properly compile a collection?
Does anyone have any idea why CoCreateInstance would be failing on ITaskBarList3 on Windows 7 64-bit? The error code is 0x80040154, which is Class Not Registered.
The calling code (VB6) is:
Public Const IID_ITaskbarList3 = "{EA1AFB91-9E28-4B86-90E9-9E9F8A5EEFAF}"
Public Const CLSID_TaskbarList3 = "{EA1AFB91-9E28-4B86-90E9-9E9F8A5EEFAF}"
'....
Dim IID As GUID_API
Dim CLSID As GUID_API
Dim iTaskBarVB3 As ShellLib.ITaskbarList3
rc = CLSIDFromString(StrPtr(CLSID_TaskbarList3), CLSID)
rc = IIDFromString(StrPtr(IID_ITaskbarList3), IID)
rc = CoCreateInstance(CLSID, 0, CLSCTX_SERVER, IID, iTaskBarVB3)
The returns from CLSIDFromString and IIDFromString are both 0 (Success). I can find the string in the registry. Since my taskbar is obviously working just fine, I know the interface is able to be called by other processes just fine.
ITaskBarList3 is declared in a typelib compiled using mktyplib.exe. I've double checked the GUID values, and they match those in the SDK.
Any help would be greatly appreciated.
The most likely reason is that the calling code is 32-bit and the COM server is 64-bit and therefore can't be loaded as an in-proc server.
A possible solution could be to create a COM+ application for the COM server to force its creation as an out-proc server. However this will not help if the COM server is meant to supply an ActiveX control.
I'm also surprised to see the class id being equal to the interface id - it's common practice to have them different. Since you are not the developer of the component implementing that interface but only the consumer it's likely that you just misplaced the class id with the interface id and this is the reason why your client program is not working. You should find the class id of the class implementing the ITaskBarList3 interface and use it as the class id.
CLSID_TaskbarList3 doesn't exist! It's simply,
CLSID_TaskbarList = "{56FDF344-FD6D-11D0-958A-006097C9A090}"
which indeed has a different GUID than the IID_TaskbarList3 IID.
In COM you have typically one class implementing one or more interface. There doesn't generally exist a new class for every interface.
The ClassID wasn't the problem, as this worked correctly about a week ago. I was previously compiling on Windows Vista, 32-bit.
I've now updated my system to Windows 7, 64-bit. The problem isn't a matter of 32/64-bit compatibility. The TaskBar is accessible through Wow64, and I am able to call the interface just fine from a 32-bit ATL DLL.
I did some more searching, and I found a number of references on the web regarding problems with actxprxy.dll on 64-bit windows. This is the DLL where the interfaces appear to reside, according to OLE Viewer.
Anyways, some people have had luck with various combinations of .reg scripts and unregistering/re-registering the files. Unfortunately, I'm not one of those people.
I've decided to save myself the headache, and just wrote a small DLL using ATL, and I have the VB code calling that. Works fine in that setup...
Thanks again for your help.
I need to open a html help file from within a legacy windows application written in old version of C++ Builder. HtmlHelp is loaded via HtmlHelp.ocx, which I am loading via LoadLibrary.
This has worked fine for years, but it does not work anymore in Windows 7 x64. It might also fail under Windows7 x86, but I don't have any computer with this OS, so I can't try it out at the moment.
I am loading hhctrl.ocx dynamically as follows:
#define HHPathRegKey "CLSID\\{adb880a6-d8ff-11cf-9377-00aa003b7a11}\\InprocServer32"
bool THTMLHelper::LoadHtmlHelp()
{
HKEY HHKey;
DWORD PathSize = 255;
char Path[255];
bool R = false;
if (::RegOpenKeyExA(HKEY_CLASSES_ROOT, HHPathRegKey, 0, KEY_QUERY_VALUE, (void **)&HHKey) == ERROR_SUCCESS)
{
if (::RegQueryValueExA(HHKey, "", NULL, NULL, (LPBYTE)Path, &PathSize) == ERROR_SUCCESS)
{
//*****************************************
//LOADING FAILS HERE
//PATH IS %SystemRoot%\System32\hhctrl.ocx
//*****************************************
HHLibrary = ::LoadLibrary(Path);
if (HHLibrary != 0)
{
__HtmlHelp = (HTML_HELP_PROC) ::GetProcAddress(HHLibrary, "HtmlHelpA");
R = (__HtmlHelp != NULL);
if (!R)
{
::FreeLibrary(HHLibrary);
HHLibrary = 0;
}
}
}
::RegCloseKey(HHKey);
}
return R;
}
I checked if %SystemRoot%\System32\hhctrl.ocx exists on the Windows 7 system and it does.
Why does loading it via LoadLibrary fail? How can I work around this problem?
EDIT: GetLastError says (in German, so I am just translating): "Could not find file." But I debugged the function and the path is "%SystemRoot%\System32\hhctrl.ocx" and the file does exist.
Also, since two answers point in the direction of 64-bit vs 32-bit problems: My application is a 32 bit executable compiled in C++ Builder 5, so it should be a 32 bit process if I'm not mistaken. Or am I wrong to assume that?
Use ExpandEnvironmentStrings function to expand %SystemRoot%\System32\hhctrl.ocx to real path on user's intallation. 64bit OS will redirect expanded path to 32bit dll correctly.
You can't load 32bit dlls in a 64bit process, and visa versa. ActiveX controls are, of course, Dlls.
You can sometimes work around this by getting the 32bit ActiveX to load as an out-of-process server - its then hosted in a seperate 32bit (or 64bit) process as appropriate. This requires that the ActiveX onlyuses interfaces the system already knows how to marshal, and/or the project built 64bit AND 32bit versions of the proxy stub dll.
Depends is a tool that is very useful when you need to figure out why Dlls wont load. Of course, as a 32 bit application on a 64bit OS you need to know that 32 bit applications do NOT get access to %SYSTEMROOT%\System32 and, also do NOT read and write from HKCR directly. System32 actually contains the 64bit OS binaries, and HKCR contains the registry entries for 64bit apps.
A kernel process called 'reflection' redirects 32bit apps completely transparently to from System32 to %SYSTEMROOT%\SysWow64.
Likewise, registry access to HKEY_CLASSES_ROOT is redirected to `HKEY_CLASSES_ROOT\Wow6432Node'.
You need to know this of course, because explorer and regedit are 64bit processes and will happily show you the 64bit contents of System32 and HKCR. You need to explicitly navigate to the 32bit nodes to double check the view your 32bit process is going to get.
I have the exact same problem right now running W7 (x64).
I got it to work when I changed the "%SystemRoot%\System32\hhctrl.ocx" to "c:\windows\System32\hhctrl.ocx", but I guess I need to figure out why %SystemRoot% resolves wrong.
btw: I'm building a 32bit app on BCB2007.
In VS9, when i call the GetTickCount() function, it automatically converts it into the GetTickCount64() function upon compilation. This second function only works on Vista+, and thus my program errors when run on XP.
How can I 'over-ride' this so that it calls the original GetTickCount() ?
Thanks
Set WINVER to the version of windows you want to target. Or maybe it's _WIN32_WINNT or _WIN32_WINDOWS. Maybe even all of them...
Take a look at http://blogs.msdn.com/oldnewthing/archive/2007/04/11/2079137.aspx for details on that small mess-o-version macros.
However, I don't see that redefinition at all in the Windows SDK - could there be something else in our setup that's doing the redefinition (or maybe I'm missing it...)?
Remember that you're not compiling your application for Vista or Windows XP, rather you're compiling for a 32-bit or 64-bit operating system. If your application needs to support other versions of Windows than 64-bit Vista, then specify in your build options to be 32-bit.
I set the following inside targetver.h:
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
#define _WIN32_WINDOWS 0x0501
and it still gets re-defined. However, when i create a simple new project that prints out GetTickCount(), it works fine on XP even without me having to define the above.
I did not change anything in the project settings. The only difference between the sample GetTickCount() that works and the one that doesn't is that it has plenty of other code around it and using it, but none of that code should be changing anything.
What could be causing this?
EDIT: One of the other files I was using was calling GetTickCount64() directly, and I did not know about this, so I assumed it was my own GetTickCount() function. Please ignore what i wrote above