/* Copyright (c) 2010 Daniel Doubrovkine, All Rights Reserved
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.  
 */
package com.sun.jna.platform.win32;

import java.util.Arrays;
import java.util.List;

import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.win32.StdCallLibrary;

/**
 * Ported from WinCrypt.h.
 * Microsoft Windows SDK 6.0A.
 * @author dblock[at]dblock.org
 */
public interface WinCrypt extends StdCallLibrary {
	
    /**
     * The CryptoAPI CRYPTOAPI_BLOB structure is used for an arbitrary array of bytes.
     */
    public static class DATA_BLOB extends Structure {
        public DATA_BLOB() {
            super();
        }
		
        public DATA_BLOB(Pointer memory) {
            super(memory);
            read();
        }

        public DATA_BLOB(byte [] data) {
            pbData = new Memory(data.length);
            pbData.write(0, data, 0, data.length);
            cbData = data.length;
            allocateMemory();
        }
		
        public DATA_BLOB(String s) {
            this(Native.toByteArray(s));
        }
		
        /**
         * The count of bytes in the buffer pointed to by pbData. 
         */
        public int cbData;
        /**
         * A pointer to a block of data bytes. 
         */
        public Pointer pbData;
        
        protected List getFieldOrder() {
            return Arrays.asList(new String[] { "cbData", "pbData" });
        }
        /**
         * Get byte data.
         * @return
         *  Byte data or null.
         */
        public byte[] getData() {
            return pbData == null ? null : pbData.getByteArray(0, cbData);
        }
    } 
	
    /**
     * The CRYPTPROTECT_PROMPTSTRUCT structure provides the text of a prompt and 
     * information about when and where that prompt is to be displayed when using
     * the CryptProtectData and CryptUnprotectData functions. 
     */
    public static class CRYPTPROTECT_PROMPTSTRUCT extends Structure {
        public CRYPTPROTECT_PROMPTSTRUCT() {
            super();
        }

        public CRYPTPROTECT_PROMPTSTRUCT(Pointer memory) {
            super(memory);
            read();
        }
		
        /**
         * Size of this structure in bytes.
         */
        public int cbSize;
        /**
         * DWORD flags that indicate when prompts to the user are to be displayed.
         */
        public int dwPromptFlags;
        /**
         * Window handle to the parent window. 
         */
        public HWND hwndApp;
        /**
         * A string containing the text of a prompt to be displayed. 
         */
        public String szPrompt;
        
        protected List getFieldOrder() {
            return Arrays.asList(new String[] { "cbSize", "dwPromptFlags", "hwndApp", "szPrompt" });
        }
    }
	
    //
    // CryptProtect PromptStruct dwPromtFlags
    //

    /**
     * Prompt on unprotect.
     */
    int CRYPTPROTECT_PROMPT_ON_UNPROTECT = 0x1; // 1<<0
    /**
     * Prompt on protect.
     */
    int CRYPTPROTECT_PROMPT_ON_PROTECT = 0x2; // 1<<1
    /**
     * Reserved, don't use.
     */
    int CRYPTPROTECT_PROMPT_RESERVED = 0x04; 
    /**
     * Default to strong variant UI protection (user supplied password currently).
     */
    int CRYPTPROTECT_PROMPT_STRONG = 0x08; // 1<<3
    /**
     * Require strong variant UI protection (user supplied password currently).
     */
    int CRYPTPROTECT_PROMPT_REQUIRE_STRONG = 0x10; // 1<<4

    //
    // CryptProtectData and CryptUnprotectData dwFlags
    //
    /**
     * For remote-access situations where ui is not an option, if UI was specified 
     * on protect or unprotect operation, the call will fail and GetLastError() will 
     * indicate ERROR_PASSWORD_RESTRICTION.
     */
    int CRYPTPROTECT_UI_FORBIDDEN = 0x1;
    /**
     * Per machine protected data -- any user on machine where CryptProtectData 
     * took place may CryptUnprotectData.
     */
    int CRYPTPROTECT_LOCAL_MACHINE = 0x4;
    /**
     * Force credential synchronize during CryptProtectData() 
     * Synchronize is only operation that occurs during this operation.
     */
    int CRYPTPROTECT_CRED_SYNC = 0x8;
    /**
     * Generate an Audit on protect and unprotect operations.
     */
    int CRYPTPROTECT_AUDIT = 0x10;
    /**
     * Protect data with a non-recoverable key.
     */
    int CRYPTPROTECT_NO_RECOVERY = 0x20;
    /**
     * Verify the protection of a protected blob.
     */
    int CRYPTPROTECT_VERIFY_PROTECTION = 0x40;
    /**
     * Regenerate the local machine protection.
     */
    int CRYPTPROTECT_CRED_REGENERATE = 0x80;
}
