views:

34

answers:

2

In the IsMemberOfAdministratorsGroup example in MSDN, there is code like this:

if (!OpenThreadToken (GetCurrentThread(), TOKEN_QUERY|TOKEN_DUPLICATE, TRUE, &hToken))
{
  if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_DUPLICATE, &hToken))
  {
    lastErr = GetLastError();
    goto CLEANUP;
  }
}

....

CLEANUP:
  if (hToken)
  {
     CloseHandle (hToken);
     hToken = NULL;  // Set variable to same state as resource.
  }

I don't see why we need to try to close the token handle if OpenThreadToken() or OpenProcessToken() fails. Is there a special condition when the two functions fail, but the handle is allocated? Or it is simply a typo (they are human anyway)?

+1  A: 

If they both fail, hToken will still be 0, and CloseHandle() won't be called....

jwismar
@jwismar: Thanks, how to format the code properly in StackOverflow.com?
Phantom
There is a Code button (010101 etc) in the form toolbar when you are entering Qs and As - select the code you wish to format and press this button
Steve Townsend
or indent the code with an extra 4 spaces.
pmg
Thanks @jwismar and @pmg, I'll try it.
Phantom
A: 

Your selective editing of the code example hides the fact that in the original code there is a lot of logic between the OpenprocessToken calls and the CLEANUP label. In the normal case (where there is no error on getting one or other of the tokens), CLEANUP is therefore required to close the opened handle.

It's a brute force way of doing try...finally logic that works even if the token handle could not be obtained.

If both calls fail, hToken will be unset and you don't have to close it.

Steve Townsend
Oh yup, a brute force way! I hate it. :-)
Phantom
But we can also just return FALSE instead of goto CLEANUP, right?
Phantom
Sorry, I mean just Exit after proper setlasterror.
Phantom
Yes, @Phantom, in that specific case, it's OK to return immediately, or throw immediately if GetLastError returns non-zero. But that breaks consistency. Everywhere else in the function, early termination needs to jump to the end to do cleanup. It's more consistent, and thus easier to understand, if *all* error cases jump to the same place. If the function changes to do some kind of resource allocation beforehand, then an early return or throw will be wrong because it will skip the resource-releasing code at the end of the function.
Rob Kennedy