views:

83

answers:

1

Several have pointed out that there exists an undocumented message that retrieves the IShellBrowser interface pointer from the common dialog HWND for the file open & save dialogs.

But there is conflicting information (or no information) on whether that pointer is AddRef'd, or if it is just the raw address returned, and no Release() should be called on it?

+2  A: 

No. You might find the following link useful: The Rules of the Component Object Model .

Excerpt:

Reference-Counting Rules

Rule 1: AddRef must be called for every new copy of an interface pointer, and Release called for every destruction of an interface pointer, except where subsequent rules explicitly permit otherwise.

The following rules call out common nonexceptions to Rule 1.

  • Rule 1a: In-out-parameters to functions. The caller must AddRef the actual parameter, since it will be Released by the callee when the out-value is stored on top of it.
  • Rule 1b: Fetching a global variable. The local copy of the interface pointer fetched from an existing copy of the pointer in a global variable must be independently reference counted, because called functions might destroy the copy in the global while the local copy is still alive.
  • Rule 1c: New pointers synthesized out of "thin air." A function that synthesizes an interface pointer using special internal knowledge, rather than obtaining it from some other source, must do an initial AddRef on the newly synthesized pointer. Important examples of such routines include instance creation routines, implementations of IUnknown::QueryInterface, and so on.
  • Rule 1d: Returning a copy of an internally stored pointer. After the pointer has been returned, the callee has no idea how its lifetime relates to that of the internally stored copy of the pointer. Thus, the callee must call AddRef on the pointer copy before returning it.

Rule 2: Special knowledge on the part of a piece of code of the relationships of the beginnings and the endings of the lifetimes of two or more copies of an interface pointer can allow AddRef/Release pairs to be omitted.

  • From a COM client's perspective, reference-counting is always a per-interface concept. Clients should never assume that an object uses the same reference count for all interfaces.
  • The return values of AddRef and Release should not be relied upon, and should be used only for debugging purposes.
  • Pointer stability; see details in the OLE Help file under "Reference-Counting Rules," subsection "Stabilizing the this Pointer and Keeping it Valid."

See the excellent "Managing Object Lifetimes in OLE" technical article by Douglas Hodges, and Chapter 3 of Inside OLE, 2nd edition, by Kraig Brockschmidt (MSDN Library, Books) for more information on reference-counting.

arul
Sorry - I'm feeling a bit thick. But your first statement is "No.", as in no I don't need to release() the returned IShellBrowser* - yet the documentation for Rule 1 (and esp. its non-exceptions) seem to indicate that the pointer that I am being handed would have been AddRef'd on my behalf (just as QueryInterface would have done).
Mordachai
You can call AddRef() / Release() manually on that object if you want, as stated in the Rule 1c (by `want` I mean that the lifetime of the object is managed by the window manager). But you *don't* need to call only Release().
arul
So it is your understanding that this is a special case 1c (I can see how that makes some sense based on the title of 1c). And if that is the case, 1c says basically that it is neither an out, nor an in, nor an inout parameter, but a synthesized one, and as such would need to be both AddRef'd and Released by the caller (or, as is obviously the case here, neither unless I tried to hold the pointer for longer than the lifetime of the current IShellBrowser, which isn't going to happen in my custom OPENFILEDIALOG handler).
Mordachai
Yes, it fits the best.
arul