internal static int EnumeratePackages(SecurDll Dll, out int pkgnum, out SafeFreeContextBuffer pkgArray)
 {
     int num = -1;
     switch (Dll)
     {
         case SecurDll.SECURITY:
         {
             SafeFreeContextBuffer_SECURITY handle = null;
             num = UnsafeNclNativeMethods.SafeNetHandles_SECURITY.EnumerateSecurityPackagesW(out pkgnum, out handle);
             pkgArray = handle;
             break;
         }
         case SecurDll.SECUR32:
         {
             SafeFreeContextBuffer_SECUR32 r_secur = null;
             num = UnsafeNclNativeMethods.SafeNetHandles_SECUR32.EnumerateSecurityPackagesA(out pkgnum, out r_secur);
             pkgArray = r_secur;
             break;
         }
         case SecurDll.SCHANNEL:
         {
             SafeFreeContextBuffer_SCHANNEL r_schannel = null;
             num = UnsafeNclNativeMethods.SafeNetHandles_SCHANNEL.EnumerateSecurityPackagesA(out pkgnum, out r_schannel);
             pkgArray = r_schannel;
             break;
         }
         default:
             throw new ArgumentException(SR.GetString("net_invalid_enum", new object[] { "SecurDll" }), "Dll");
     }
     if ((num != 0) && (pkgArray != null))
     {
         pkgArray.SetHandleAsInvalid();
     }
     return num;
 }
        //
        //
        internal static int EnumeratePackages(SecurDll Dll, out int pkgnum, out SafeFreeContextBuffer pkgArray) {

            int res = -1;
            switch (Dll) {
            case SecurDll.SECURITY:
                SafeFreeContextBuffer_SECURITY pkgArray_SECURITY = null;
                res = UnsafeNclNativeMethods.SafeNetHandles_SECURITY.EnumerateSecurityPackagesW(out pkgnum, out pkgArray_SECURITY);
                pkgArray = pkgArray_SECURITY;
                break;

            default: throw new ArgumentException(SR.GetString(SR.net_invalid_enum, "SecurDll"), "Dll");
            }
            if (res != 0 && pkgArray != null) {
                pkgArray.SetHandleAsInvalid();
            }
            return res;
        }
        //
        // After PINvoke call the method will fix the handleTemplate.handle with the returned value.
        // The caller is responsible for creating a correct SafeFreeContextBuffer_XXX flavour or null can be passed if no handle is returned.
        //
        // Since it has a CER, this method can't have any references to imports from DLLs that may not exist on the system.
        //
        private static unsafe int MustRunAcceptSecurityContext_SECURITY(
                                                  ref SafeFreeCredentials     inCredentials,
                                                  void*            inContextPtr,
                                                  SecurityBufferDescriptor inputBuffer,
                                                  ContextFlags     inFlags,
                                                  Endianness       endianness,
                                                  SafeDeleteContext outContext,
                                                  SecurityBufferDescriptor outputBuffer,
                                                  ref ContextFlags outFlags,
                                                  SafeFreeContextBuffer handleTemplate)
        {
            int errorCode = (int) SecurityStatus.InvalidHandle;
            bool b1 = false;
            bool b2 = false;

            // Run the body of this method as a non-interruptible block.
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                inCredentials.DangerousAddRef(ref b1);
                outContext.DangerousAddRef(ref b2);
            }
            catch(Exception e)
            {
                if (b1)
                {
                    inCredentials.DangerousRelease();
                    b1 = false;
                }
                if (b2)
                {
                    outContext.DangerousRelease();
                    b2 = false;
                }
                if (!(e is ObjectDisposedException))
                    throw;
            }
            finally {
                SSPIHandle credentialHandle = inCredentials._handle;
                long timeStamp;

                if (!b1)
                {
                    // caller should retry
                    inCredentials = null;
                }
                else if (b1 && b2)
                {
                    errorCode = UnsafeNclNativeMethods.SafeNetHandles_SECURITY.AcceptSecurityContext(
                                ref credentialHandle,
                                inContextPtr,
                                inputBuffer,
                                inFlags,
                                endianness,
                                ref outContext._handle,
                                outputBuffer,
                                ref outFlags,
                                out timeStamp);

                    //
                    // When a credential handle is first associated with the context we keep credential
                    // ref count bumped up to ensure ordered finalization.
                    // If the credential handle has been changed we de-ref the old one and associate the
                    //  context with the new cred handle but only if the call was successful.
                    if (outContext._EffectiveCredential != inCredentials && (errorCode & 0x80000000) == 0)
                    {
                        // Disassociate the previous credential handle
                        if (outContext._EffectiveCredential != null)
                            outContext._EffectiveCredential.DangerousRelease();
                        outContext._EffectiveCredential = inCredentials;
                    }
                    else
                    {
                        inCredentials.DangerousRelease();
                    }

                    outContext.DangerousRelease();

                    // The idea is that SSPI has allocated a block and filled up outUnmanagedBuffer+8 slot with the pointer.
                    if (handleTemplate != null)
                    {
                        handleTemplate.Set(((SecurityBufferStruct*)outputBuffer.UnmanagedPointer)->token); //ATTN: on 64 BIT that is still +8 cause of 2* c++ unsigned long == 8 bytes
                        if (handleTemplate.IsInvalid)
                        {
                            handleTemplate.SetHandleAsInvalid();
                        }
                    }
                }

                if (inContextPtr == null && (errorCode & 0x80000000) != 0)
                {
                    // an error on the first call, need to set the out handle to invalid value
                    outContext._handle.SetToInvalid();
                }
            }

            return errorCode;
        }