/*
         * Windows creates a new ticket cache for primary NT tokens. This allows callers to create a dedicated cache for whatever they're doing
         * that way the cache operations like purge or import don't polute the current users cache.
         *
         * To make this work we need to create a new NT token, which is only done during logon. We don't actually want Windows to validate the credentials
         * so we tell it to treat the logon as `NewCredentials` which means Windows will just use those credentials as SSO credentials only.
         *
         * From there a new cache is created and any operations against the "current cache" such as SSPI ISC calls will hit this new cache.
         * We then let callers import tickets into that cache using the krb-cred structure.
         *
         * When done the call to dispose will
         * 1. Revert the impersonation context
         * 2. Close the NT token handle
         * 3. Close the Lsa Handle
         *
         * This destroys the cache and closes the logon session.
         *
         * For any operation that require native allocation and PtrToStructure copies we try and use the CryptoPool mechanism, which checks out a shared
         * pool of memory to create a working for the current operation. On dispose it zeros the memory and returns it to the pool.
         */

        internal unsafe TicketCacheWriter(LsaSafeHandle lsaHandle, string packageName = _kerberosPackageName)
        {
            _lsaHandle = lsaHandle;

            var kerberosPackageName = new NativeMethods.LSA_STRING
            {
                Buffer        = packageName,
                Length        = (ushort)packageName.Length,
                MaximumLength = (ushort)packageName.Length
            };

            var result = NativeMethods.LsaLookupAuthenticationPackage(_lsaHandle, ref kerberosPackageName, out _selectedAuthPackage);

            NativeMethods.LsaThrowIfError(result);

            var negotiatePackageName = new NativeMethods.LSA_STRING
            {
                Buffer        = _negotiatePackageName,
                Length        = (ushort)_negotiatePackageName.Length,
                MaximumLength = (ushort)_negotiatePackageName.Length
            };

            result = NativeMethods.LsaLookupAuthenticationPackage(_lsaHandle, ref negotiatePackageName, out _negotiateAuthPackage);
            NativeMethods.LsaThrowIfError(result);
        }
 public static unsafe extern int LsaCallAuthenticationPackage(
     LsaSafeHandle LsaHandle,
     int AuthenticationPackage,
     void *ProtocolSubmitBuffer,
     int SubmitBufferLength,
     out LsaBufferSafeHandle ProtocolReturnBuffer,
     out int ReturnBufferLength,
     out int ProtocolStatus
     );
 public static extern int LsaConnectUntrusted(
     [Out] out LsaSafeHandle LsaHandle
     );
 public static extern int LsaLookupAuthenticationPackage(
     LsaSafeHandle LsaHandle,
     ref LSA_STRING PackageName,
     out int AuthenticationPackage
     );