[C#] Calling An Office DLL Help

Discussion in 'Mixed Languages' started by CODYQX4, Dec 7, 2010.

  1. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,804
    45,135
    150
    #1 CODYQX4, Dec 7, 2010
    Last edited by a moderator: Apr 20, 2017
    Well there are functions inside a DLL called OSPPC.dll that give us a few more tools.

    An example is we could uninstall licenses and get the rearm count (and not by taking backup, counting rearms, then restoring)

    Here is info MasterDisaster Posted
    Code:
    Available commands:
    
        Initialize
        ActivateProduct                       SkuId
        Close
        ConsumeRight                          [AppId | ? | ??] [SkuId]
        DepositOfflineConfirmationId          [SkuId | ?] [IID] [CID]
        FireEvent                             [AppId | ?] ['LICENSING_STATE_CHANGED'|.]
        GenerateOfflineInstallationId         [SkuId | ?]
        GetGenuineInformation                 [AppId | ?] [BRTData|BRTCommit|GenuineResult|NonGenuineGraceFlag]
        GetInstalledAppIds                    [SkuId | ?]
        GetInstalledSkuIds
        GetInstalledPKeyIds                   [SkuId | ?]
        GetLicenseFileId                      LicenseFileName
        GetLicenseFileIdsByLicenseId          LicenseId
        GetLicenseIdsByLicenseFileId          LicenseFileId
        GetLicenseIdsBySkuId                  SkuId
        GetLicenseInformation                 LicenseId ['Description' | 'LicenseType' | 'Version']
        GetLicensingStatus                    [AppId | ? | ??] [SkuId] ['Minutes']
        GetPKeyId                             5x5PKey
        GetPKeyIdsBySkuId                     [SkuId | ?]
        GetPKeyInformation                    PKeyId ['DigitalPID' | 'DigitalPID2' | 'Pid2' | 'PartialProductKey' | 'ProductSkuId' | 'PKHash' | 'Channel' | 'IsTrialPKey']
        GetPackageProperties                  LicensePackageFileName
        GetPackageProductKey                  LicensePackageFileName
        GetPackageToken                       LicensePackageFileName TokenIndex
        GetPolicyInformation                  PolicyName
        GetProductSkuInformation              [SkuId | ?] ['Name' | 'Description' |'Author' | 'Licensor' | 'TimeBasedExtendedGrace']
        GetServiceInformation                 ['Version']
        GetApplicationInformation             [AppId | ?] ['RearmCount' | 'RemainingRearmCount' | 'TrustedTime']
        InstallLicense                        LicenseFileName
        InstallLicensePackage                 LicensePackageFileName
        InstallProofOfPurchase                5x5PKey [ |PKeyAlgorithm]
        IsGenuineLocal                        [AppId | ? | ??] [SkuId]
        Open
        RegisterPlugin                        dll manifest
        SetCurrentPKey                        [SkuId | ?] PKeyId
        SetGenuineInformation                 [AppId | ?] [BRTData|BRTCommit] Value
        UninstallLicense                      LicenseFileId
        UninstallLicensePackage               LicensePackageFileName
        UninstallProofOfPurchase              PKeyId
        UnregisterPlugin                      manifest
        @ReadEvents                           [MachineName|.] [NumOfRecords|.] [EventId]
        @DecodeBase64                         Base64FileName BinaryFileName
        @EncodeBase64                         BinaryFileName Base64FileName
        @DeactiveOnline                       [SkuId | ?]
        @GetActivatedLicenseId                [SkuId | ?] [Private|Public]
        @GetActivatedLicenseFileId            [SkuId | ?]
        @GenerateRSAKeyPair                   [SIGNATURE|KEYEXCHANGE] KeyLength PubKeyFileName PriKeyFileName
        @EncryptData                          KeyFile ClearFile CipherFile
        @DecryptData                          KeyFile CipherFile ClearFile
        @PrintBinaryData                      BinaryFile
        GetTokenActivationCertificates        [SkuId | ?] Flags
        DepositTokenActivationResponse        SkuId CertId
        PersistRTSPayloadOverride             [AppId | ? | ??] Value [SkuId]
        GetReferralInformation                [AppId | SkuId | ? | ??] Type ValueName
        PersistApplicationPolicies            [AppId | ? | ??] SkuId Flags
        LoadApplicationPolicies               [AppId | SkuId | ? | ??] Flags
        GetApplicationPolicy                  PolicyName
        UnloadApplicationPolicies             Flags
        Rearm                                 [AppId | ? | ??] [SkuId | *] Flags
        GetAuthenticationResponse             TypeId
        AcquireGenuineTicket                  TemplateId ServerUrl
        @GetModuleHash                        FilePath
    I'd like to be able to call the GetApplicationInformation function in C# but don't know how (PS: It might actually be named SLGetApplicationInformation)

    It returns the rearm count as we need. I need the C# one but if you could also help do it in batch, timesurfer could use it in IORRT.

    The DLL is in this folder if you got Office 2010 installed
    C:\Program Files\Common Files\Microsoft Shared\OfficeSoftwareProtectionPlatform

    or

    C:\Program Files(x86)\Common Files\Microsoft Shared\OfficeSoftwareProtectionPlatform

    You'll be helping in improving the toolkit and any help will be greatly appreciated.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  2. Daz

    Daz MDL Developer / Admin
    Staff Member

    Jul 31, 2009
    9,431
    66,402
    300
    #2 Daz, Dec 7, 2010
    Last edited by a moderator: Apr 20, 2017
    Looked into the DLL before, only a little but I wasn't able to figure out the calls being made. Just for example it could be:
    Code:
    BOOL GetApplicationInformation(
    __inLPCTSTR lpAppID,
    __inDWORD dwType,
    __outLPTSTR lpBuffer
    );
    I'm not sure if anyones put any time trying to find out the API function calls but without these it's a dead end.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  3. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,804
    45,135
    150
    #3 CODYQX4, Dec 7, 2010
    Last edited by a moderator: Apr 20, 2017
    (OP)
    That's my issue. It's not publicly documented so I haven't the slightest clue how to set it up, what to pass it, and what and how it will return.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  4. Daz

    Daz MDL Developer / Admin
    Staff Member

    Jul 31, 2009
    9,431
    66,402
    300
    #4 Daz, Dec 7, 2010
    Last edited: Dec 7, 2010
    It could result in a few hours of trial and error testing. If you get close the error codes for the function call will start changing too.

    That example actually has an issue. Its return type would likely be DWORD so that you know how much info was returned... Then again theres a ton of ways a function could be wrote and I'm tired anyway :p
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  5. timesurfer

    timesurfer MDL Developer

    Nov 22, 2009
    8,527
    4,067
    270
    How could this be used in IORRT if I never check rearms. Would this be a way to see if IORRT would work based on if it had say 0 rearms it would return a error msg? Is that what you mean?
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  6. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,804
    45,135
    150
    Yes as it returns the rearm count as a number if it works right. Somehow the ospprun.exe uses this to show rearms.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  7. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,804
    45,135
    150
    OK the functions I wanted to test are useless so nobody waste their time on this. Maybe some of those other functions have use and could be investigated like the Encrypt/Decrypt stuff but I haven't the slightest clue for how and what they would be used for.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  8. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,804
    45,135
    150
    OK figuring the SLGetApplicationInformation for rearm count may be useful again.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  9. woot332

    woot332 MDL Senior Member

    Feb 18, 2011
    390
    808
    10
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  10. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,804
    45,135
    150
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  11. woot332

    woot332 MDL Senior Member

    Feb 18, 2011
    390
    808
    10
    Had a look at OSPPREARM.EXE to see if SLGetApplicationInformation is used to return rearm
    count. It seems SLGetApplicationInformation is not called see code below, maybe upload ospprun.exe?.

    push eax
    CALL SLOpen

    PUSH EAX ; /Arg2
    PUSH 2D591190 ; |Arg1 = UNICODE "{59a52881-a989-479d-af46-f275c6370663}"
    CALL ole32.CLSIDFromString

    PUSH EBX
    PUSH EBX
    LEA EAX,[EBP-14]
    PUSH EAX
    PUSH DWORD PTR SS:[EBP-18]
    CALL SLReArm

    SLReArm stack
    Address Value ASCII Comments
    0036FEB4 /003F6CB8 hSLC
    0036FEB8 |0036FED4 pApplicationId 16 byte return by CLSIDFromString
    0036FEBC |00000000 pProductSkuId
    0036FEC0 |00000000 dwFlags

    PUSH DWORD PTR SS:[EBP-18]
    CALL SLClose
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  12. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,804
    45,135
    150
    I don't have ospprun.exe, but I know it does this call.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  13. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,804
    45,135
    150
    #13 CODYQX4, May 2, 2013
    Last edited by a moderator: Apr 20, 2017
    (OP)
    OK deagles managed to get the rearm count using C++.

    I am trying to do this using p/Invoke but I am getting a messed up number.

    This is the C# Code (note my test case is Office 2013 x86 on Windows x64, so the ospp stuff is not run, but the spp stuff is):
    Code:
            /// <summary>
            /// Obtain the remaining number of Rearms for Microsoft Office
            /// </summary>
            /// <returns>Remaining Rearm Count Number</returns>
            public static int GetRearmCount()
            {
                // Rearm Count
                int rearmCount;
    
                // Microsoft Office Application ID
                Guid officeAppID = Guid.Empty;
    
                // Use Microsoft Office or Windows Software Protection Platform
                bool useOSPP = true;
    
                // Initialize Microsoft Office Application Specific Information
                if (OfficeVersion.GetOfficeNumber() == 14)
                {
                    officeAppID = new Guid("59a52881-a989-479d-af46-f275c6370663");
                }
                else if (OfficeVersion.GetOfficeNumber() == 15)
                {
                    officeAppID = new Guid("0ff1ce15-a989-479d-af46-f275c6370663");
                    useOSPP = !(OSVersion.GetWindowsNumber() >= 6.2);
                }
    
                // Target the desired Software Licensing Service
                if (useOSPP)
                {
                    // Load Library
                    IntPtr osppDllHandle = NativeMethods.LoadLibrary(GetOSPPCPath());
    
                    // Handles
                    IntPtr osppHandle = IntPtr.Zero;
    
                    // Open Handle to Microsoft Office Software Licensing Service
                    NativeMethods.OSPPOpen(ref osppHandle);
    
                    // Get Microsoft Office Remaining Rearm Count from OSPP
                    uint descSize = 0;
                    IntPtr descBuffer = IntPtr.Zero;
                    SLDATATYPE slDataType = SLDATATYPE.SL_DATA_DWORD;
                    NativeMethods.OSPPGetApplicationInformation(osppHandle, ref officeAppID, "RemainingRearmCount", ref slDataType, ref descSize, ref descBuffer);
                    rearmCount = descBuffer.ToInt32();
    
                    // Close Handle to Microsoft Office Software Licensing Service
                    NativeMethods.OSPPClose(osppHandle);
                    NativeMethods.FreeLibrary(osppDllHandle);
                }
                else
                {
                    // Load Library
                    IntPtr sppDllHandle = NativeMethods.LoadLibrary("sppc.dll");
    
                    // Handles
                    IntPtr sppHandle = IntPtr.Zero;
    
                    // Open Handle to Microsoft Windows Software Licensing Service
                    NativeMethods.SPPOpen(ref sppHandle);
    
                    // Get Microsoft Office Remaining Rearm Count from SPP
                    uint descSize = 0;
                    IntPtr descBuffer = IntPtr.Zero;
                    SLDATATYPE slDataType = SLDATATYPE.SL_DATA_DWORD;
                    NativeMethods.SPPGetApplicationInformation(sppHandle, ref officeAppID, "RemainingRearmCount", ref slDataType, ref descSize, ref descBuffer);
                    rearmCount = descBuffer.ToInt32();
    
                    // Close Handle to Microsoft Windows Software Licensing Service
                    NativeMethods.SPPClose(sppHandle);
                    NativeMethods.FreeLibrary(sppDllHandle);
                }
    
                // Return Rearm Count
                return rearmCount;
            }
    
    P/Invoke definitions:
    Code:
         internal enum SLDATATYPE
        {
            // ReSharper disable InconsistentNaming
            SL_DATA_NONE = 0,
            SL_DATA_SZ = 1,
            SL_DATA_DWORD = 4,
            SL_DATA_BINARY = 3,
            SL_DATA_MULTI_SZ = 7,
            SL_DATA_SUM = 100,
            // ReSharper restore InconsistentNaming
        }
    
        internal static class NativeMethods
        {
            [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
            internal static extern IntPtr LoadLibrary(string lpFileName);
    
            [DllImport("kernel32.dll", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern bool FreeLibrary(IntPtr hModule);
    
            #region Microsoft Office Software Protection Service
            [DllImport("osppc.dll", EntryPoint = "SLOpen", CharSet = CharSet.Unicode)]
            internal static extern int OSPPOpen(ref IntPtr phSLC);
    
            [DllImport("osppc.dll", EntryPoint = "SLClose", CharSet = CharSet.Unicode)]
            internal static extern int OSPPClose(IntPtr hSLC);
    
            [DllImport("osppc.dll", EntryPoint = "SLGetApplicationInformation", CharSet = CharSet.Unicode)]
            internal static extern int OSPPGetApplicationInformation(IntPtr hSLC, ref Guid pApplicationId, [InAttribute] [MarshalAsAttribute(UnmanagedType.LPWStr)] string pwszValueName, ref SLDATATYPE peDataType, ref uint pcbValue, ref IntPtr ppbValue);
            #endregion
    
            #region Microsoft Windows Software Protection Service
            [DllImport("sppc.dll", EntryPoint = "SLOpen", CharSet = CharSet.Unicode)]
            internal static extern int SPPOpen(ref IntPtr phSLC);
    
            [DllImport("sppc.dll", EntryPoint = "SLClose", CharSet = CharSet.Unicode)]
            internal static extern int SPPClose(IntPtr hSLC);
    
            [DllImport("sppc.dll", EntryPoint = "SLGetApplicationInformation", CharSet = CharSet.Unicode)]
            internal static extern int SPPGetApplicationInformation(IntPtr hSLC, ref Guid pApplicationId, [InAttribute] [MarshalAsAttribute(UnmanagedType.LPWStr)] string pwszValueName, ref SLDATATYPE peDataType, ref uint pcbValue, ref IntPtr ppbValue);
            #endregion
        }
    
    PS: Tried slc.dll instead of sppc.dll, didn't help.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  14. PAYMYRENT

    PAYMYRENT MDL Developer

    Jul 28, 2009
    1,462
    419
    60
    try SLOpen_0 for your entry point
     
  15. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,804
    45,135
    150
    #15 CODYQX4, May 3, 2013
    Last edited: May 3, 2013
    (OP)
    Unable to find an entry point named 'SLOpen_0' in DLL 'sppc.dll'.

    That is the error I get, which suggests that it did in fact find SPOpen.

    PS: Based on purposely changing entry point and dll name, it indicates that it is in face getting the right DLL and finding the entry point.

    I don't think it is getting the descBuffer right.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  16. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,804
    45,135
    150
    #16 CODYQX4, May 3, 2013
    Last edited: May 3, 2013
    (OP)
    Specifically, I get a message like this:
    You have 26470712 Available Rearms.

    The number on quick subsequent checks varies slightly but is close, and it seems like a memory address, like the descBuffer variable isn't working right.

    PS: Do I need LoadLibrary and FreeLibrary? I get the same thing if I comment that out.

    I've only ever needed those for MasterDisaster based C# PIDX Checker.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  17. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,804
    45,135
    150
    #17 CODYQX4, May 3, 2013
    Last edited: May 3, 2013
    (OP)
    I think I might have it.

    I made the descBuffer a byte[1]. I got 3 rearms for Office and 232 for Windows. Really it is 3 and 1000, sounds like I made byte[] too small so I'm trying byte[4].

    EDIT: Nope. For some reason it returns a byte[1] even when I send a byte[4].
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  18. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,804
    45,135
    150
    #18 CODYQX4, May 3, 2013
    Last edited by a moderator: Apr 20, 2017
    (OP)
    Here is the code:
    Code:
            /// <summary>
            /// Obtain the remaining number of Rearms for Microsoft Windows
            /// </summary>
            /// <returns>Remaining Rearm Count Number</returns>
            public static int GetRearmCount()
            {
                // Microsoft Windows Application ID
                Guid windowsAppID = new Guid("55c92734-d682-4d71-983e-d6ec3f16059f");
    
                // Load Library
                IntPtr sppDllHandle = NativeMethods.LoadLibrary("Slc.dll");
    
                // Handles
                IntPtr sppHandle = IntPtr.Zero;
    
                // Open Handle to Microsoft Windows Software Licensing Service
                NativeMethods.SPPOpen(ref sppHandle);
    
                // Get Microsoft Office Remaining Rearm Count from SPP
                uint descSize = 0;
                byte[] descBuffer = new byte[4];
                SLDATATYPE slDataType = SLDATATYPE.SL_DATA_DWORD;
                NativeMethods.SPPGetApplicationInformation(sppHandle, ref windowsAppID, "RemainingRearmCount", ref slDataType, ref descSize, ref descBuffer);
    
                // Close Handle to Microsoft Windows Software Licensing Service
                NativeMethods.SPPClose(sppHandle);
                NativeMethods.FreeLibrary(sppDllHandle);
    
                // Return Rearm Count
                return descBuffer[0];
            }
    
    ... and the P/Invoke:
    Code:
            #region Microsoft Windows Software Protection Service
            [DllImport("Slc.dll", EntryPoint = "SLOpen", CharSet = CharSet.Unicode)]
            internal static extern int SPPOpen(ref IntPtr phSLC);
    
            [DllImport("Slc.dll", EntryPoint = "SLClose", CharSet = CharSet.Unicode)]
            internal static extern int SPPClose(IntPtr hSLC);
    
            [DllImport("Slc.dll", EntryPoint = "SLGetApplicationInformation", CharSet = CharSet.Unicode)]
            internal static extern int SPPGetApplicationInformation(IntPtr hSLC, ref Guid pApplicationId, [InAttribute] [MarshalAsAttribute(UnmanagedType.LPWStr)] string pwszValueName, ref SLDATATYPE peDataType, ref uint pcbValue, ref byte[] ppbValue);
            #endregion
    
    Rearm count is good for Office 2013 x86 on Windows 8 x64, but Windows 8 x64 itself gives 232 instead of 1000.

    Also, I had 3 rearms for Office, code for Office gives 3, it also goes down to 2 just fine when I rearm office.

    PS: The reason why I believe there is an overflow or something:

    1000:
    1111101000

    232:
    11101000

    See that the binary 1000 last 8 bits = 232, it seems to cut off at 8.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...
  19. deagles

    deagles MDL Developer

    Feb 22, 2013
    239
    1,174
    10
    #19 deagles, May 3, 2013
    Last edited by a moderator: Apr 20, 2017
    Code:
    byte[] descBuffer = new byte[4];
    
    GetApplicationInformation allocates a buffer itself.
    You only need a 32bit unsigned int pointer.
    ( descSize == 4 bytes )

    What does GetApplicationInformation return?
    ( 0x80070057 == One or more arguments are not valid. )
     
  20. CODYQX4

    CODYQX4 MDL Developer

    Sep 4, 2009
    4,804
    45,135
    150
    #20 CODYQX4, May 3, 2013
    Last edited by a moderator: Apr 20, 2017
    (OP)
    Setting descSize to 4 has no effect.

    Also, using anything but a ref byte[] descBuffer fails and gives an 8 digit number like above.

    The documentation here says to bass a PBYTE so I used ref byte[].

    I get the Office Rearm correct in all possible cases on Windows 8 x64 for 2010 and 2013, but not Windows, with it's 232 rearm count bug.
     
    Stop hovering to collapse... Click to collapse... Hover to expand... Click to expand...