|
-
October 22nd, 2002, 01:48 PM
#1
FormatMessage in ATL COM problem
I'm having a problem with FormatMessage in ATL COM object.
I have a basic ATL COM dll that has a message in its string table defined:
IDS_UPDATES_AVAILABLE - Some string with places to fill %1 type strings....
I'm trying to use FormatMessage API to retrieve and format this string, and I'm getting weird problems with it. Here is the code:
Code:
LPTSTR lpFinalMessage = NULL;
LPTSTR lpUpdateComments = NULL;
lpUpdateComments = _T("Some sort of string...");
DWORD dwRetVal = ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY, _Module.GetResourceInstance(), IDS_UPDATES_AVAILABLE, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpFinalMessage, 500, &lpUpdateComments);
DWORD dwErr = GetLastError();
Problem is: FormatMessage always returns 0, and error code doesn't make that much sense.
The way the code is above, error returned in 1813 - The specified resource type cannot be found in the image file. A) IDS string thingy is definately there (it wouldn't really compile otherwise), and B) I'm not specifying type anywhere - it is basic String Table. (By the way, changing next to last parameter from 500 to 0 or any other number doesn't change anything).
If I try to simplify - remove FORMAT_MESSAGE_FROM_HMODULE and pass NULL instead of _Module.GetResourceInstance(), I get error 87 - The parameter is incorrect.
Anyone has any idea what is going on???
-
October 22nd, 2002, 02:08 PM
#2
If you specify FORMAT_MESSAGE_FROM_HMODULE in the dwFlags parameter then the FormatMessage function will scan the module specified in the second parameter lpSource for a message table ressource (a ressource which is compiled by the message compiler - a normal string table entry is quite different from that).
You have to use FORMAT_MESSAGE_FROM_STRING in dwFlags. Your call might look like this:
Code:
...
CString s;
s.LoadString(IDS_UPDATES_AVAILABLE);
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING| FORMAT_MESSAGE_ARGUMENT_ARRAY,
(LPCVOID)(LPCSTR) s,
0, //ignored
0, //ignored
(LPTSTR) &lpFinalMessage,
500,
&lpUpdateComments);
-
October 22nd, 2002, 02:15 PM
#3
Hmm, I didn't think that messages from MC and string table would be different things... OK, can you the suggest me how to use this without MFC?
LoadString does not say how big the string in the resource is...
I can't quite figure out the appropriate code for it.
PS What is the principal difference between MC strings, and String Table strings???
Originally posted by alpha137
If you specify FORMAT_MESSAGE_FROM_HMODULE in the dwFlags parameter then the FormatMessage function will scan the module specified in the second parameter lpSource for a message table ressource (a ressource which is compiled by the message compiler - a normal string table entry is quite different from that).
You have to use FORMAT_MESSAGE_FROM_STRING in dwFlags. Your call might look like this:
Code:
...
CString s;
s.LoadString(IDS_UPDATES_AVAILABLE);
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING| FORMAT_MESSAGE_ARGUMENT_ARRAY,
(LPCVOID)(LPCSTR) s,
0, //ignored
0, //ignored
(LPTSTR) &lpFinalMessage,
500,
&lpUpdateComments);
-
October 23rd, 2002, 03:02 AM
#4
I actually don't know if and how the compiled format of a string table differs from the format of a message table. But I'm sure that these are at least different ressource types.
If you don't have MFC then LoadString is also a "basic" SDK function and declared as:
Code:
int LoadString(
HINSTANCE hInstance,
UINT uID,
LPTSTR lpBuffer,
int nBufferMax
);
You can't determine the size needed for lpBuffer before calling LoadString but you can call the function in a loop (resizing the buffer every time) until it returns a lower number of bytes copied than the size of your buffer is.
But anyway - you have the same problem with your lpFinalMessage parameter.
You didn't tell why you are using FormatMessage but if you want to report an COM error then have a look at the AtlReportError function.
-
October 23rd, 2002, 10:49 AM
#5
I'm aware of LoadString, and currently trying to implement it in the code.
With FormatMessage, I don't need to know the final size, since I can simply ask FormatMessage to allocate memory for me.
This is not for error reporting - this is to retrieve a string to display in a message box - but I don't want to hard code the string, but rather to do it like it is suppose to be done.
My strategy right now is to try to use SizeofResource() function to find out the size of the string, and then use LoadString().
Will post here on progress for those who are interested...
Originally posted by alpha137
I actually don't know if and how the compiled format of a string table differs from the format of a message table. But I'm sure that these are at least different ressource types.
If you don't have MFC then LoadString is also a "basic" SDK function and declared as:
Code:
int LoadString(
HINSTANCE hInstance,
UINT uID,
LPTSTR lpBuffer,
int nBufferMax
);
You can't determine the size needed for lpBuffer before calling LoadString but you can call the function in a loop (resizing the buffer every time) until it returns a lower number of bytes copied than the size of your buffer is.
But anyway - you have the same problem with your lpFinalMessage parameter.
You didn't tell why you are using FormatMessage but if you want to report an COM error then have a look at the AtlReportError function.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|