///<summary>
            /// Creates the structure that holds byte[] data to be encrypted.
            ///</summary>
            ///<param name="data">Data to be encrypted.</param>
            ///<returns>Structure that holds byte[] data to be encrypted.</returns>
            ///<exception cref="MemberAccessException">Unable to allocate data buffer for BLOB structure</exception>
            public static DPAPINativeDATABLOB Init(byte[] data)
            {
                // Use empty array for null parameter.
                if (data == null)
                {
                    data = new byte[0];
                }

                var blob = new DPAPINativeDATABLOB
                           {
                               DataPointer = Marshal.AllocHGlobal(data.Length),
                               DataLength = data.Length
                           };

                // Make sure that memory allocation was successful.
                // With the null check on the data parameter, I don't think this is needed.
                //if (blob.pbData == IntPtr.Zero)
                //    throw new MemberAccessException("Unable to allocate data buffer for BLOB structure.");

                // Copy data from original source to the BLOB structure.
                Marshal.Copy(data, 0, blob.DataPointer, data.Length);

                return blob;
            }
 ///<summary>
 /// Performs encryption on the data in a <see cref="DPAPINativeDATABLOB"/> structure
 ///</summary>
 ///<param name="plainText">Structure that contains the plaintext to be encrypted.</param>
 ///<param name="description">A readable description of the data to be encrypted.</param>
 ///<param name="entropy">Structure that contains a password or other additional entropy used to encrypt the data.</param>
 ///<param name="reserved">Reserved for future use and must be set to NULL.</param>
 ///<param name="prompt">Structure that provides information about where and when prompts are to be displayed and what the content of those prompts should be.</param>
 ///<param name="flags">Crypt Protection</param>
 ///<param name="cipherText">Structure that receives the encrypted data.</param>
 ///<returns>If the function succeeds, then <c>TRUE</c> else <c>FALSE</c>.</returns>
 private static bool ProtectData(ref DPAPINativeDATABLOB plainText,
                                 string description,
                                 ref DPAPINativeDATABLOB entropy,
                                 IntPtr reserved,
                                 ref DPAPINativeCRYPTPROTECTPROMPTSTRUCT prompt,
                                 int flags,
                                 ref DPAPINativeDATABLOB cipherText)
 {
     return CryptProtectData(ref plainText, description, ref entropy, reserved, ref prompt, flags, ref cipherText);
 }
 private static extern bool CryptUnprotectData(ref DPAPINativeDATABLOB cipherText,
                                               ref string description,
                                               ref DPAPINativeDATABLOB entropy,
                                               IntPtr reserved,
                                               ref DPAPINativeCRYPTPROTECTPROMPTSTRUCT prompt,
                                               int flags,
                                               ref DPAPINativeDATABLOB plainText);
        private static byte[] DPAPIDecrypt(byte[] cipherText, byte[] entropy)
        {
            // Create BLOBs to hold data.
            var plainTextBlob = new DPAPINativeDATABLOB();
            var cipherTextBlob = new DPAPINativeDATABLOB();
            var entropyBlob = new DPAPINativeDATABLOB();

            // We only need prompt structure because it is a required parameter.
            var prompt = DPAPINativeCRYPTPROTECTPROMPTSTRUCT.Default();

            byte[] plainTextBytes;

            try
            {
                // Convert ciphertext bytes into a BLOB structure.
                cipherTextBlob = DPAPINativeDATABLOB.Init(cipherText);

                // Convert entropy bytes into a BLOB structure.
                entropyBlob = DPAPINativeDATABLOB.Init(entropy);

                // Initialize description string.
                string description = String.Empty;

                // Call DPAPI to decrypt data.
                bool success = UnprotectData(ref cipherTextBlob, ref description, ref entropyBlob, IntPtr.Zero, ref prompt,
                                             CRYPTPROTECT_UI_FORBIDDEN, ref plainTextBlob);

                // Check the result.
                if (!success)
                {
                    // If operation failed, retrieve last Win32 error.
                    int errCode = Marshal.GetLastWin32Error();

                    // Win32Exception will contain error message corresponding
                    // to the Windows error code.
                    throw new CryptographicException("CryptUnprotectData failed.", new Win32Exception(errCode));
                }

                // Allocate memory to hold plaintext.
                plainTextBytes = new byte[plainTextBlob.DataLength];

                // Copy ciphertext from the BLOB to a byte array.
                Marshal.Copy(plainTextBlob.DataPointer, plainTextBytes, 0, plainTextBlob.DataLength);
            }
            catch (Exception ex)
            {
                throw new CryptographicException("DPAPI was unable to decrypt data.", ex);
            }
            finally
            {
                // Free all memory allocated for BLOBs.
                plainTextBlob.Dispose();
                cipherTextBlob.Dispose();
                entropyBlob.Dispose();

                prompt.Dispose();
            }

            // Return the result.
            return plainTextBytes;
        }