|
I have a COM dll Win32 developed with C++.
I want to create 2 different versions :
- One in 32 Bits
- One in 64 Bits
This 2 dll must be usable on the same PC by different applications.
How can I do this ?
Also,I know how to build dll in X64, But have they the same guid or not?
|
|
|
|
|
Both DLLs can have the same GUID.
When registering 32-bit and 64-bit DLLs, the registry entries created for each of them are in different registry locations.
So it is possible for both of them to be used of the same PC using the same GUID.
When a 32-bit application creates an instance of the COM, the registry access will be redirected to the appropriate location and it will find the 32-bit COM DLL.
And a 64-bit application will create the 64-bit COM DLL.
|
|
|
|
|
|
The terms in capitals are used in MFC and are not specific to the C++ language. The remaining terms are functions used in the C++ libraries. The return value of a function is defined by the function definition. All this information can be found by searching MSDN; a starting point for C++ is here[^].
Unrequited desire is character building. OriginalGriff
I'm sitting here giving you a standing ovation - Len Goodman
|
|
|
|
|
rk12180 wrote: Requesting assistance soon.
I gave you assistance over 6 hours ago. I suggest you follow the link I provided and start reading up on some of these terms.
Unrequited desire is character building. OriginalGriff
I'm sitting here giving you a standing ovation - Len Goodman
|
|
|
|
|
Still its not getting clear. I need some information about the stuff that i gave before not the link from you. I'm using vs6.0. is there anything you want to know additionally? 
|
|
|
|
|
I explained what the terms were; the MFC macros you can find in the documentation for MFC or the header files where they are defined. The other macros will be similarly defined in the Win32 header files. I am reasonably sure that you can find them all with a simple search of MSDN. Perhaps if you explained exactly what problem you are trying to solve we can make some more suggestions.
Unrequited desire is character building. OriginalGriff
I'm sitting here giving you a standing ovation - Len Goodman
|
|
|
|
|
Compiling C++ with MS VS 2010, and getting an error when the initializer list for a derived class has a fully-qualified name for the base class constructor. Example:
class base {
public:
base(int i);
...
};
class myclass : public base {
public:
myclass();
...
};
myclass::myclass() : base::base(123)
{
...
The GNU compiler on Linux is quite happy, but the MS compiler objects to the (unnecessary) qualification of the base class constructor; it insists on:
myclass::myclass() : base(123)
{
...
What I'd really like to know is, which compiler is wrong? The C++ standard should either allow or prohibit the extra qualification, but I can't find an online copy of a standard.
It's only a problem because of a lot of code in a project that I've inherited is written that way; it used to compile on older versions of MS, but no longer.
|
|
|
|
|
I'm afraid the standard won't help you there, unless you can use it to bend VC2010's behavior somehow - this, assuming VC2010 is the one actually wrong.
Sadly, a regex-based search-and-replace may be the only practical option you have there: I assume you already tried playing with compiler flags, to no avail.
JM2B,
Pablo.
"Accident: An inevitable occurrence due to the action of immutable natural laws." (Ambrose Bierce, circa 1899).
|
|
|
|
|
I'm not sure about the standard but MSDN has a reference[^] to it and Bjarne Stroustrup[^] also has lots of information. One thing you might try is check the diagnostic message that the MS compiler produces and see if it can be suppressed by the use of a #pragma , without causing other errors.
Unrequited desire is character building. OriginalGriff
I'm sitting here giving you a standing ovation - Len Goodman
|
|
|
|
|
Hi,
I have a COM dll with a class in it. This class alters the registry at HKLM\Software\Policies\MyPolicy
The DLL has a UAC execution level of Highest Available (I think I had it still happen with asInvoker as well).
The executable that cals this dll has an execution level of invoker.
If I run this as administrator, I get the UAC prompt when my class gets invoked, and I see all my debug messages in dbgview and any debug message boxes show up.
If I log in as standard user, and right click runas administrator, everything works fine.
However, If I simply double-click, I see the UAC elevation prompt when my class gets invoked. I enter in the correct password, and the COM object creation passes, but the Registry is never changed, AND I do not see any debug messages or message boxes. If I turn off "Run all administrators in admin approval mode", I see the messages, but the program fails to set the registry keys.
Anybody have any clues? Also, do you know of any great debuggers that I may use to solve this?
More Info:
I am building it in VS 2008, but it is using visual studio version 2.0 with MFC setting to 'using standard windows libraries' and Use of ATL set to 'Dynamic Link to ATL'
I explicitly add the additional registry settings to get the elevation to work in the DllRegisterServer function.
I add the following keys to the registry:
HKLM\Software\Classes\AppID\My AppGuid(found in dllMain.h)>\ROTFlags(a string set to "1")
HKLM\Software\Classes\AppID\My AppGuid\DllSurrogate(a string set to empty)
HKLM\Software\Classes\CLSID\My ClassID (found in ClassName.rgs)\AppID (a string set to My AppGuid)
HKLM\Software\Classes\CLSID\My ClassID\LocalizedString (an expanding string set to @dllPath.dll,-100(where 100 is a string
in the string table)).
HKLM\Software\Classes\CLSID\My ClassID\Elevation\Enabled (a DWORD set to 1)
HKLM\Software\Classes\CLSID\My ClassID\Elevation\IconReference (An expanding string set to 'applicationIcon')
Also, my calling code uses the standard old
HRESULT CallingClass::CoCreateInstanceAsAdmin(HWND hwnd,REFCLSID rClsid, REFIID rIid, void** ppv)
{
try
{
HRESULT hr;
BIND_OPTS3 bo;
WCHAR wszCLSID[255];
WCHAR wszMonikerName[300];
StringFromGUID2(rClsid,wszCLSID,sizeof(wszCLSID)/sizeof(wszCLSID[0]));
hr = StringCchPrintf(
wszMonikerName,sizeof
(wszMonikerName)/
sizeof(wszMonikerName[0]),
L"Elevation:Administrator!new:%s",
wszCLSID);
if(FAILED(hr))
{
. . .ShowMyDebugMessage
return hr;
}
memset(&bo, 0, sizeof(bo));
bo.cbStruct = sizeof(bo);
bo.hwnd = hwnd;
bo.dwClassContext = CLSCTX_LOCAL_SERVER;
return CoGetObject(wszMonikerName,
&bo, rIid, ppv );
}
catch(...)
{
. . .Show my debug message
return E_FAIL;
}
return S_OK;
}
Christine Murphy
C# developer
|
|
|
|
|
Hello,
I'm trying to upgrade a program from Visual C++ 6 to Visual C++ 2008.
However, there have been some changes to the STL library.
I used to store an iterator (which was 4 Bytes in size) inside an MFC CListBox using SetItemData and restored it with GetItemData.
However, the iterators are now 12 Bytes in size. I could in principle store only the NodePtr
listBox.SetItemDataPtr(index, iter._Ptr);
...
iter = list<int>::iterator((list<int>::_Nodeptr)listBox.GetItemDataPtr(index), &stl_list);
The only problem is that the type
list<int>::_Nodeptr is protected, so I cannot convert it back.
Do you have any idea how to temporarily store the iterator inside the ListBox?
Alex
|
|
|
|
|
Why not store a pointer to the iterator, or indeed to the list that it's an iterator of?
iter = list<int>::iterator((list<int>::_Nodeptr)listBox.GetItemDataPtr(index), &stl_list);
listBox.SetItemDataPtr(index, &iter);
Unrequited desire is character building. OriginalGriff
I'm sitting here giving you a standing ovation - Len Goodman
|
|
|
|
|
Sorry, but that does not make sense.
&iter points (in my case) to the stack and is invalid at the latest when the function (where I store it) exits. I could surely create a new iterator on the heap using new (but then I would have to make sure that all stored iterators are destroyed when the ListBox is destroyed ...). However, this should in principle not be necessary (as the only information I have to store is the pointer to the node).
Alex
|
|
|
|
|
LionAM wrote: However, this should in principle not be necessary (as the only information I have to store is the pointer to the node).
Without knowing more about what you are trying to do it's not easy to make a more sensible suggestion. Ultimately I guess you need to store some information about a variable in the entry's ListItem . In all cases I have needed to do this I have used either an index into an array or list, or a pointer if the item is not an elementary type. Those are the choices you have, it's up to you to decide which is the more useful in your particular application.
Unrequited desire is character building. OriginalGriff
I'm sitting here giving you a standing ovation - Len Goodman
|
|
|
|
|
In principle, I have a CListBox object and an STL list<...> object. The items in the list<...> should be reflected in the CListBox.
When I remove any item from the CListBox, it should be removed from the list<...>, too. Therefore, I stored the (raw data of the) iterator to the corresponding list<...> item within the CListBox item. This was no problem in Visual C++ 6 as
sizeof(list<...>::iterator) == sizeof(void*)
However, this is not the case in Visual C++ 2008. Together with the pointer to the node, the pointer to the list (_Mycont) and some other pointer (_Mynextiter) are stored inside the iterator. You can, in principle, construct a new iterator knowing only the pointer to the node (iter._Ptr) and the pointer to the parent list.
However, I cannot convert from void* back to list<...>::_NodePtr:
void* data = listBox.GetItemData(index);
iter.Ptr = (list<...>::_NodePtr)data;
Alex
|
|
|
|
|
I have not used list but it may be that it is not the best container for this situation; perhaps a map would provide what you want.
Unrequited desire is character building. OriginalGriff
I'm sitting here giving you a standing ovation - Len Goodman
|
|
|
|
|
Everything was working as expected under Visual C++ 6.
For Visual C++ 2008, I found a (not very elegant) workaround. As I cannot directly convert to _NodePtr,
I take another iterator, write the data to the memory position of the _NodePtr member and create a new iterator:
list<...>::iterator temp;
*(void**)&temp._Ptr = listBox.GetItemDataPtr(index);
iter = list<...>::iterator(temp._Ptr, &stl_list);
Alex
|
|
|
|
|
LionAM wrote: Everything was working as expected under Visual C++ 6.
That may have been luck; you should never rely on an object being the same size as a pointer.
Unrequited desire is character building. OriginalGriff
I'm sitting here giving you a standing ovation - Len Goodman
|
|
|
|
|
I did not rely on it - I had checked this with a STATIC_ASSERT(...) macro.
But when I tried to compile the program with VC2008, this failed.
(indeed, if I hadn't used the STATIC_ASSERT, I would perhaps still wonder why the program does not work as expected...)
Alex
|
|
|
|
|
My statement was made as a general statement of principle: pointers (which have a constant size) are not the same as objects (whose size may change).
Unrequited desire is character building. OriginalGriff
I'm sitting here giving you a standing ovation - Len Goodman
|
|
|
|
|
All keywords that begin with and underscore followed by a capital letter (_Nodeptr) are reserved for use internally by the standard C++ library and must not be used. Also, it is not a good idea to store iterators because they will be invalidated whenever the any change happens to the container. So, for example, if one item is deleted from the list, some of the iterators will become invalid.
|
|
|
|
|
I agree that these internal members may change for different STL versions.
But, at least for STL list, all iterators remain valid as long as you do not remove the corresponding item from the list. This is guaranteed by the standard.
Have you a better idea how to store a reference to some item of a doubly linked list within the CListBox, so that I can add another item before/after the selected item or to remove the corresponding item from the STL list?
Alex
|
|
|
|
|
Don't store iterators, it's not a good idea. I'd say that you should take the opportunity to refactor the code a bit.
If you're not going to remove or add elements inside the list (I assume not, since that could invalidate iterators), you could use a std::vector instead, and store the indices in the listbox. This would also give constant-time access, just like having an iterator already.
If you are going to add or remove in the middle of the list, use a std::map with an autoincrementing unsigned int as a key, and store that key in the listbox.
Both of these solutions are safe in the face of change.
|
|
|
|
|
Thank you for your answer.
Surely, I am adding and removing elements from the STL (doubly linked) list. That is the purpose of the CListBox control.
The STL list lives, in principle, for the whole program lifetime. If I want to change the contents of the list, I create a child window with the CListBox control and populate it with the items of the list (together with the iterator). To add a new item before/after the currently selected item in the CListBox control, I use the iterator to find the corresponding item in the STL list. When I want to delete an item, its the same.
This works, as the iterators of the STL list are guaranteed to be valid as long as you don't delete the corresponding item.
For my case, a map would not work as it does not remember the ordering of the items. To store the indices of the vector would not make sense as these change if one item is inserted or removed. The doubly linked list seems, in principle, to be the best choice due to the constant insert/remove time.
Alex
|
|
|
|