4

I have a function in an IUnknown-derived COM interface:

HRESULT GetPassword( [in] long bufferLength, [out] WCHAR* buffer );

and the contract is that the implementation should check whether the buffer is large enough to store the string being retrieved. If the buffer is large enough the string is copied and S_OK is returned, otherwise the function will return an error indication.

However I can't find a suitable HRESULT value for that. E_UNEXPECTED seems quite dumb and unhelpful. The closest I found is DISP_E_BUFFERTOOSMALL but looks like it is for IDispatch-derived interfaces only.

Which HRESULT should I returned if a buffer provided is too small?

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
sharptooth
  • 167,383
  • 100
  • 513
  • 979

4 Answers4

4

You can't return DISP_E_* errors, you are not implementing IDispatch. E_INVALIDARG is correct here, it is even unambiguous which doesn't happen too often. Always implement ISupportErrorInfo to generate good error messages, ATL makes it trivial with the Error() method.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • why can't he return DISP_E_*? I mean, I get that it seems inconsistent, but it is more specific than "Invalid Argument", and what is the actual practical risk? – tenfour Feb 19 '11 at 13:22
  • The programmer won't think the error is caused by his code. Bad. – Hans Passant Feb 19 '11 at 15:27
  • I don't agree. Many COM objects forward inner error messages up the stack to the caller. So even if his interface is not a `IDispatch`, maybe an object that it *uses* is. This is so common, no programmer would actually be confused by it. But I think the whole topic is a bit subjective :) – tenfour Feb 19 '11 at 16:30
  • You gave the *exact* reason why the programmer thinks it is not his code. – Hans Passant Feb 19 '11 at 16:36
1

As lame as it sounds, E_INVALIDARG is probably your best bet, technically speaking. There are not so many standard HRESULTs which are more specific for arguments. There is also E_POINTER but it would probably be more confusing.

I would consider using DISP_E_BUFFERTOOSMALL. This will be intuitive to callers, and the only risk would be that they don't recognize it because it's not in the standard set of generic HRESULT values. I think that's a pretty small risk though, for a pretty small problem :)

tenfour
  • 36,141
  • 15
  • 83
  • 142
  • Well, `E_INVALIDARG` would be perfect in case for example the buffer size passed is negative or zero, but any positive number is okay in general, just in this very case the buffer is not large enough. – sharptooth Feb 18 '11 at 10:25
  • "Invalid" doesn't mean "invalid in general". "Invalid right now in this context" is also just as "invalid". But yea anyway I hate that message because it's so over-used. Personally I would use `DISP_E_BUFFERTOOSMALL`. – tenfour Feb 18 '11 at 10:41
1

You shouldn't return an error. You should succeed, fill the buffer with what you can, and return through another parameter how big the buffer needs to be.

If you don't do it this way, how does the caller discover how big a buffer to allocate? You don't seriously want them to call repeatedly, with progressively bigger buffers, until they hit upon a value that suffices? I would hate to have to use such an interface!

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 1
    In the spirit of best practices, why go half way way? He should return a `BSTR`. – tenfour Feb 18 '11 at 10:43
  • @tenfour or a LPWCHAR* that was allocated with the COM allocator, if you have an allergy to `BSTR`. But yes, a grown up string type would be better than these painful C strings. – David Heffernan Feb 18 '11 at 10:45
  • You're of course right, but COM interfaces never change once introduced and the implementor has to stick to what already exists. – sharptooth Feb 18 '11 at 10:50
  • @sharptooth I read the Q that the interface was under development, and therefore could be altered. Could be wrong though, it has happened before!! – David Heffernan Feb 18 '11 at 10:52
  • Bravo @tenfour! If you still have the control to change the interface, do return a `BSTR` instead. Everybody will be happier. – Euro Micelli Feb 18 '11 at 14:29
1

If you can still do something about it, you should really consider changing the interface to return a BSTR instead of a WCHAR*. It simplifies a lot of things.

Sometimes you can, sometimes you cannot.

Credit should go to @tenfour for suggesting this. Since you can't post and forward your upvotes to someone else, I'm posting as community wiki.

Euro Micelli
  • 33,285
  • 8
  • 51
  • 70