views:

143

answers:

3

Microsoft Office documents, im my case: PowerPoint presentations, can have restricted permissions. How can I find out, programmatically, which permissions my code has on a given document?

All I can find on MSDN on this topic is this: http://msdn.microsoft.com/en-us/library/aa432118.aspx

If I run the following code, I get a list of users that have permissions on the given document:

Sub test()
    Dim perm As Office.Permission
    Set perm = ActivePresentation.Permission
    Debug.Print "Enabled=" & perm.Enabled
    If perm.Enabled Then
        Debug.Print "PermissionFromPolicy=" & perm.PermissionFromPolicy
        Debug.Print "PolicyName='" & perm.PolicyName & "'"
        Debug.Print "PolicyDescription='" & perm.PolicyDescription & "'"
        Dim uperm As Office.UserPermission
        For Each uperm In perm
            Debug.Print uperm.UserId & ", " & uperm.Permission
        Next uperm
    End If
End Sub

Sample output:

Enabled=True
PermissionFromPolicy=False
PolicyName='Do Not Distribute'
PolicyDescription='Permission is currently restricted. Only specified users can access this content.'
[email protected], 64
[email protected], 33
[email protected], 33

The "Permission" is a bitmap the definition for which I found in Microsoft's public COM header files:

enum MsoPermission
{
  msoPermissionView = 1,
  msoPermissionRead = 1,
  msoPermissionEdit = 2,
  msoPermissionSave = 4,
  msoPermissionExtract = 8,
  msoPermissionChange = 15,
  msoPermissionPrint = 16,
  msoPermissionObjModel = 32,
  msoPermissionFullControl = 64,
  msoPermissionAllCommon = 127
};

Still, this does not tell me which particular permissions my code has. If I only knew who I am (in terms of a UserPermission.UserId), I could look up my permissions in the Permission object. But I cannot find that bit of information. What am I missing?

There are known ways to obtain the Windows user name (the login name for the current user on that Windows machine). Unfortunately, this is not the user id that is checked against when PowerPoint decides which permissions I have on the document. To emphasize: PowerPoint provides a UI that lets me change "who I am" at run time. Obviously, this does not change the login use name (i.e., the name returned by ADVAPI). The user names PowerPoint is referring to, are identified/authorized via Microsoft's Passport.

Thanks in advance!
Volker

+1  A: 

Try one of the functions GetUserName(), GetUserNameW() or GetUserNameA() and declare it thusly:

Private Declare Function GetUserName Lib "advapi32.dll" Alias _
    "GetUserName" (ByVal lpBuffer As String, nSize As Long) As Long

Also see MSDN about GetUserName.

You need to dim a string with length 255 and pass 254 as parameter nSize. This string is passed ByVal back to the caller. Perhaps you need to left() the string before you can use it to compare it with uperm.UserId.

nalply
If time permits, I will follow-up with a complete solution. But perhaps this is already enough to get you started.
nalply
Thank you nalply, I think I know what to do. No need to take more time for a complete solution... I'll let you know if I succeed.
vschoech
nalply, what I get following your advice is the Windows user name (the login name for the current user on that Windows machine). Unfortunately, this is not the user id that is checked against when PowerPoint decides which permissions I have on the document.To emphasize: PowerPoint provides a UI that lets me change "who I am" at run time. Obviously, this does not change the login use name (i.e., the name returned by ADVAPI). The user names PowerPoint is referring to, are identified/authorized via Microsoft's Passport.To summarize: This question is still open to earn some points...! ;-)
vschoech
I am sorry. I don't know a lot about Microsoft Passport. I would need to learn about it. If nobody else knows an answer I would try to find an answer for you.
nalply
I found out something which might help you: http://msdn.microsoft.com/en-us/library/system.web.security.passportidentity.hexpuid(VS.80).aspx -- but this is .NET. Do you know how to call .NET from VBA?Take care.
nalply
I am still watching this question. After Christmas I will have some free time and try to find a solution, if nobody else has answered.
nalply
A: 

I have opened a ticket with Microsoft on this (SRQ091221600157). After a lengthy discussion with Microsoft Support, the ticket is still pending but I think it is already safe to say that there is no explicit way to obtain the information I need.

Microsoft explicitly states that there is no API in PowerPoint to obtain either the identity that was used to open a presentation, or the currently active permissions. A feature request to add that API has been filed.

If you are in a closed environment with your own Rights Management Server, the following approaches would probably work (quoting Microsoft Support, I did not test this myself):

1) Using the COM object ADSystemInfo object.

Dim objADSystemInfo As Object
Dim objUser As Object
objADSystemInfo = CreateObject("ADSystemInfo")
objUser = GetObject("LDAP://" + objADSystemInfo.UserName)
objUser.Get("mail")  'This will return the AD email id 

'We can use this to include in the permission related code that you had sent
If (uperm.UserId = objUser.Get("mail")) Then
    'You can get the permission uperm.Permission for this userid (current logged in)
    MsgBox(uperm.UserId & "logged in user") 
Else
    MsgBox(uperm.UserId & "other user")
End If

2) Using the .NET approach

Dim oDS = New System.DirectoryServices.DirectorySearcher
Dim strUserName As String = Environment.UserName
Dim strFilter As String = "(&(objectCategory=User)(samAccountName=" & strUserName & "))"
oDS.Filter = strFilter
Dim oSr As System.DirectoryServices.SearchResult = oDS.FindOne()
Dim oUser As System.DirectoryServices.DirectoryEntry
oUser = oSr.GetDirectoryEntry()
MessageBox.Show(oUser.InvokeGet("mail"))

Here is the article that explains about these approaches –
http://www.microsoft.com/technet/scriptcenter/resources/pstips/dec07/pstip1207.mspx

However, these approaches do not work for identities that use online IRM services (Microsoft Passport). Also, even with your own Rights Management Server, it may be possible to change your identity in PowerPoint at runtime, in which case the above approaches probably would not yield the desired results (I did not investigate this any further).

I the end, I had to come up with a workaround that tests the permissions I need by trying to run some representative API call and then checking if the call failed.

Thank you for your contributions,
Volker

vschoech
A: 

Today I received an additional answer from Microsoft (still regarding SRQ091221600157) which actually seems to solve the problem, at least in my particular instance. This approach still smells like work-around and there is no documentation that would confirm that it actually works, but it seems plausible enough and withstands some ad-hoc tests. And, it feels much less patchy than any other work-around I came up with. It goes like this:

Only users with msoPermissionFullControl can see permissions of other users (undocumented assumption). Thus, if a user does not have msoPermissionFullControl, the Permission collection contains exactly one item and this item reflects the current user's permissions. If the permission collection contains multiple items, this means that the current user must have msoPermissionFullControl. Also, the current user must be visible in the Permission collection, but there is still no way to find out which of the identities in the Permission collection represents the current user.

vschoech