C-C++ Code Example: Retrieving the Queue Owner's Name

 

Applies To: Windows 10, Windows 7, Windows 8, Windows 8.1, Windows Server 2008, Windows Server 2008 R2, Windows Server 2012, Windows Server 2012 R2, Windows Server Technical Preview, Windows Vista

The following example provides an application-defined function that receives a computer name and a queue name as input parameters and retrieves the domain name (if applicable) and account name of the queue's owner.

This function calls MQGetQueueSecurity with the SecurityInformation parameter set to OWNER_SECURITY_INFORMATION to obtain information about the owner of a specified queue from its security descriptor. MQGetQueueSecurity can be used to obtain security information for a public queue on the local or a remote computer, or for a private queue on the local computer.

For information about queue security, see Access Control.

An application using this function must include the Windows.h, Stdio.h, and Mq.h header files.

To retrieve the queue owner's name

  1. Validate the input strings.

    Note

    It is the responsibility of the caller to ensure that these strings contain only valid characters and are null-terminated.

  2. Define the variables needed to obtain the format name.

  3. Define the variables needed to retrieve information from the security descriptor.

  4. Generate the complete path name of the queue from the computer name and queue name passed to the function.

  5. Call MQPathNameToFormatName to obtain the public or private format name of the queue from its path name. This format name is used to obtain the information from the queue's security descriptor. Note that a direct format name can be used to obtain information from the security descriptor of a local private queue only.

  6. In a loop, call MQGetQueueSecurity twice to retrieve the owner information from the queue's security descriptor. The first call is made with a one-byte buffer to find out the size of the buffer needed. The second call, which is made after memory is allocated for the self-relative SECURITY_DESCRIPTOR structure needed to store the information, retrieves the component of security information requested (the owner information).

    Note

    The SecurityInformation parameter is set to OWNER_SECURITY_INFORMATION because only information about the queue's owner is retrieved.

  7. Call GetSecurityDescriptorOwner to retrieve the owner's security identifier (SID) from the security descriptor buffer. If the security descriptor contains an owner, the function sets pSID to the address of the owner SID in the security descriptor buffer. If the security descriptor does not contain owner information, the function sets pSID to NULL.

  8. Create buffers for the account name and the domain name for the SID and then call LookupAccountSid to obtain the account name and domain name.

  9. Free the memory allocated for the resources and buffers.

Code Example

The following code example can be run on computers with Windows NT® 4.0, Windows® 2000, and newer operating systems that have Message Queuing installed.

HRESULT GetQueueOwner(  
                      LPCWSTR wszComputerName,  
                      LPCWSTR wszQueueName  
                      )  
{  
  
  // Validate the input strings.  
  if (wszComputerName == NULL || wszQueueName == NULL)  
  {  
    return MQ_ERROR_INVALID_PARAMETER;  
  }  
  
  // Define the variables needed to obtain the format name.  
  DWORD dwPathNameLength = 0;  
  WCHAR * wszPathName = NULL;  
  DWORD dwFormatNameBufferLength = 256;             // Format name buffer length  
  WCHAR wszFormatNameBuffer[256];                   // Format name buffer  
  
  // Define the variables needed to retrieve security information.  
  PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;  // Pointer to a security descriptor buffer  
  DWORD dwBufferLength = 1;  
  DWORD dwBufferLengthNeeded = 1;  
  PSID pSid = NULL;  
  BOOL fOwnerExists = FALSE;  
  SID_NAME_USE eSidType;  
  DWORD dwErrorCode = 0;  
  HRESULT hr = MQ_OK;                              // Define results  
  
  // Set a size that may be sufficient for the account name and domain name buffers.  
  const DWORD INITIAL_SIZE = 256;  
  DWORD cchAccName = INITIAL_SIZE;  
  DWORD cchDomainName = INITIAL_SIZE;  
  WCHAR * wszAccName = NULL;  
  WCHAR * wszDomainName = NULL;  
  
  // Generate the complete path name of the queue.  
  dwPathNameLength = wcslen(wszComputerName) + wcslen(wszQueueName) + 2;  
  wszPathName = new WCHAR[dwPathNameLength];  
  if (wszPathName == NULL)  
  {  
    return MQ_ERROR_INSUFFICIENT_RESOURCES;  
  }  
  memset(wszPathName, 0, dwPathNameLength*sizeof(WCHAR));  
  
  // ************************************  
  // You must concatenate wszComputerName, "\", and wszQueueName  
  // the wszPathName variable.  
  // wszPathName = wszComputerName +  "\" + wszQueueName  
  // If the name is to long for the buffer, return MQ_ERROR.  
  // ************************************  
  
  wszPathName[dwPathNameLength - 1] = L'\0';  
  
  // Obtain the queue's format name from its path name.  
  hr = MQPathNameToFormatName(  
                              wszPathName,  
                              wszFormatNameBuffer,  
                              &dwFormatNameBufferLength  
                              );  
  if (FAILED(hr))  
  {  
    wprintf(L"The call to MQPathNameToFormatName failed. Error code: 0x%X\n", hr);  
    delete [] wszPathName;  
    return hr;  
  }  
  
  // Free the memory allocated for the path name buffer.  
  delete [] wszPathName;  
  
  // Retrieve the information about the queue owner from the queue's security descriptor.  
  for ( ; ; )  
  {  
    pSecurityDescriptor = (PSECURITY_DESCRIPTOR) new byte[dwBufferLength];  
    hr = MQGetQueueSecurity(  
                            wszFormatNameBuffer,   
                            OWNER_SECURITY_INFORMATION,  
                            pSecurityDescriptor,  
                            dwBufferLength,  
                            &dwBufferLengthNeeded  
                            );  
    if (SUCCEEDED(hr))  
    {  
      break;  
    }  
    if (hr == MQ_ERROR_SECURITY_DESCRIPTOR_TOO_SMALL)  
    {  
  
      // Allocate the memory needed for the security descriptor buffer.  
      delete [] pSecurityDescriptor;  
      dwBufferLength = dwBufferLengthNeeded;  
      pSecurityDescriptor = (PSECURITY_DESCRIPTOR) new byte[dwBufferLength];  
      if(pSecurityDescriptor == NULL)  
      {  
        wprintf(L"Memory could not be allocated for the security descriptor buffer.\n" );  
        return MQ_ERROR_INSUFFICIENT_RESOURCES;  
      }  
      memset(pSecurityDescriptor, 0, dwBufferLength);  
      wprintf(L"Memory for a security descriptor buffer containing %d bytes was allocated at the address %d.\n",   
              dwBufferLength, pSecurityDescriptor);  
      continue;  
    }  
    wprintf(L"The call to MQGetQueueSecurity failed. Error code: 0x%X\n", hr);  
    return hr;  
  }  
  
  // Retrieve the owner's SID from the security descriptor buffer.  
  if (GetSecurityDescriptorOwner(  
                                 pSecurityDescriptor,  
                                 &pSid,  
                                 &fOwnerExists  
                                 ) == FALSE)  
  {  
    dwErrorCode = GetLastError();  
    wprintf(L"GetSecurityDescriptorOwner failed.\n");  
    delete [] pSecurityDescriptor;  
    return HRESULT_FROM_WIN32(dwErrorCode);  
  }  
  
  if (pSid == NULL)  
  {  
    wprintf(L"No owner was found.\n");  
    return MQ_ERROR;  
  }  
  
  // Create buffers for the account name and the domain name.  
  wszAccName = new WCHAR[cchAccName];  
  if (wszAccName == NULL)  
  {  
    return MQ_ERROR_INSUFFICIENT_RESOURCES;  
  }  
  wszDomainName = new WCHAR[cchDomainName];  
  if (wszDomainName == NULL)  
  {  
    return MQ_ERROR_INSUFFICIENT_RESOURCES;  
  }  
  memset(wszAccName, 0, cchAccName*sizeof(WCHAR));  
  memset(wszDomainName, 0, cchDomainName*sizeof(WCHAR));  
  
  // Set the computer name string to NULL for the local computer.  
  if (wcscmp(wszComputerName, L".") == 0)  
  {  
    wszComputerName = L"\0";  
  }  
  
  // Obtain the account name and domain name for the SID.  
  for ( ; ; )  
  {  
  
    if (LookupAccountSidW(  
                          wszComputerName, // NULL for the local computer  
                          pSid,  
                          wszAccName,  
                          &cchAccName,  
                          wszDomainName,  
                          &cchDomainName,  
                          &eSidType  
                          ) == TRUE)  
    {  
      break;  
    }  
  
    // Check if one of the buffers was too small.  
    if ((cchAccName > INITIAL_SIZE) || (cchDomainName > INITIAL_SIZE))  
    {  
  
      // Reallocate memory for the buffers and try again.  
      wprintf(L"The name buffers were too small. They will be reallocated.\n");  
      delete [] wszAccName;  
      delete [] wszDomainName;  
      wszAccName = new WCHAR[cchAccName];  
      if (wszAccName == NULL)  
      {  
        return MQ_ERROR_INSUFFICIENT_RESOURCES;  
      }  
      wszDomainName = new WCHAR[cchDomainName];  
      if (wszDomainName == NULL)  
      {  
        return MQ_ERROR_INSUFFICIENT_RESOURCES;  
      }  
      memset(wszAccName, 0, cchAccName*sizeof(WCHAR));  
      memset(wszDomainName, 0, cchDomainName*sizeof(WCHAR));  
      continue;  
    }  
  
    // Otherwise, something else went wrong.  
    dwErrorCode = GetLastError();  
    wprintf(L"LookupAccountSidW failed.\n");  
    delete [] pSecurityDescriptor;  
    delete [] wszAccName;  
    delete [] wszDomainName;  
    FreeSid(pSid);  
    return HRESULT_FROM_WIN32(dwErrorCode);  
  }  
  
  if (wszDomainName[0] == 0)  
  {  
    wprintf(L"The queue owner is %s.\n\n", wszAccName);  
  }  
  else wprintf(L"The queue owner is %s\\%s.\n\n", wszDomainName, wszAccName);  
  
  // Free memory allocated for the resources and buffers.  
  delete [] pSecurityDescriptor;  
  delete [] wszAccName;  
  delete [] wszDomainName;  
  FreeSid(pSid);  
  return hr;  
}