//
// Softanics, Artem A. Razin, All rights reserved, Copyright 2004 - 2009
//
// BoxedApp SDK
//
// Ask your questions here: http://boxedapp.com/support.html
// Our forum: http://boxedapp.com/forum/
// License SDK: http://boxedapp.com/order.html
// Online help: http://boxedapp.com/boxedappsdk/help/
//

#ifndef __BOXEDAPPSDK_H__
#define __BOXEDAPPSDK_H__

#define BOXEDAPPSDKAPI __stdcall

#include <pshpack4.h>

// IStream* declaration
#include <objidl.h>

#ifdef __cplusplus
extern "C" {
#endif

// Options
#define DEF_BOXEDAPPSDK_OPTION__ALL_CHANGES_ARE_VIRTUAL (1) // default: 0 (FALSE)
#define DEF_BOXEDAPPSDK_OPTION__EMBED_BOXEDAPP_IN_CHILD_PROCESSES (2) // default: 1 (FALSE, don't enable BoxedApp to a new process by default)

// Initialization
BOOL BOXEDAPPSDKAPI BoxedAppSDK_Init();
// Finalization
void BOXEDAPPSDKAPI BoxedAppSDK_Exit();

// Enable / disable logging
void BOXEDAPPSDKAPI BoxedAppSDK_EnableDebugLog(BOOL bEnable);

// Log file
void BOXEDAPPSDKAPI BoxedAppSDK_SetLogFileA(LPCSTR szLogFilePath);
void BOXEDAPPSDKAPI BoxedAppSDK_SetLogFileW(LPCWSTR szLogFilePath);

#ifdef UNICODE
#define BoxedAppSDK_SetLogFile BoxedAppSDK_SetLogFileW
#else
#define BoxedAppSDK_SetLogFile BoxedAppSDK_SetLogFileA
#endif // UNICODE

void WINAPI BoxedAppSDK_WriteLogA(LPCSTR szMessage);
void WINAPI BoxedAppSDK_WriteLogW(LPCWSTR szMessage);

#ifdef UNICODE
#define BoxedAppSDK_WriteLog BoxedAppSDK_WriteLogW
#else
#define BoxedAppSDK_WriteLog BoxedAppSDK_WriteLogA
#endif // UNICODE

// Virtual file system

#ifdef UNICODE
#define BoxedAppSDK_CreateVirtualFile BoxedAppSDK_CreateVirtualFileW
#else
#define BoxedAppSDK_CreateVirtualFile BoxedAppSDK_CreateVirtualFileA
#endif // UNICODE

// Create new virtual file
HANDLE BOXEDAPPSDKAPI BoxedAppSDK_CreateVirtualFileA(
	LPCSTR szPath, 
	DWORD dwDesiredAccess,
	DWORD dwShareMode,
	LPSECURITY_ATTRIBUTES lpSecurityAttributes,
	DWORD dwCreationDisposition,
	DWORD dwFlagsAndAttributes,
	HANDLE hTemplateFile
);

HANDLE BOXEDAPPSDKAPI BoxedAppSDK_CreateVirtualFileW(
	LPCWSTR szPath, 
	DWORD dwDesiredAccess,
	DWORD dwShareMode,
	LPSECURITY_ATTRIBUTES lpSecurityAttributes,
	DWORD dwCreationDisposition,
	DWORD dwFlagsAndAttributes,
	HANDLE hTemplateFile
);

typedef enum _ENUM_BOXEDAPPSDK_FILEPROC_COMMAND
{
	EnumBoxedAppSDK_FileProcCommand__CreateContext = 1, 
	EnumBoxedAppSDK_FileProcCommand__DeleteContext = 2, 
	EnumBoxedAppSDK_FileProcCommand__Read = 3, 
	EnumBoxedAppSDK_FileProcCommand__Write = 4, 
	EnumBoxedAppSDK_FileProcCommand__Seek = 5, 
	EnumBoxedAppSDK_FileProcCommand__GetSize = 6

} ENUM_BOXEDAPPSDK_FILEPROC_COMMAND;

typedef DWORD (BOXEDAPPSDKAPI *PFILEPROC)(PVOID Param, ENUM_BOXEDAPPSDK_FILEPROC_COMMAND Command, PVOID Info);

HANDLE BOXEDAPPSDKAPI BoxedAppSDK_CreateVirtualFileExA(
	LPCSTR szPath, 
	DWORD dwDesiredAccess,
	DWORD dwShareMode,
	LPSECURITY_ATTRIBUTES lpSecurityAttributes,
	DWORD dwCreationDisposition,
	DWORD dwFlagsAndAttributes,
	HANDLE hTemplateFile, 

	PVOID Param, 
	PFILEPROC pFileProc
);
HANDLE BOXEDAPPSDKAPI BoxedAppSDK_CreateVirtualFileExW(
	LPCWSTR szPath, 
	DWORD dwDesiredAccess,
	DWORD dwShareMode,
	LPSECURITY_ATTRIBUTES lpSecurityAttributes,
	DWORD dwCreationDisposition,
	DWORD dwFlagsAndAttributes,
	HANDLE hTemplateFile, 

	PVOID Param, 
	PFILEPROC pFileProc
);

#ifdef UNICODE
#define BoxedAppSDK_CreateVirtualFileEx BoxedAppSDK_CreateVirtualFileExW
#else
#define BoxedAppSDK_CreateVirtualFileEx BoxedAppSDK_CreateVirtualFileExA
#endif // UNICODE

#define DEF_FILEPROC_COMMAND_CREATE_CONTEXT (1)
typedef struct SFileProcCreateContext
{
	// Fill this field when you handle DEF_FILEPROC_COMMAND_CREATE_CONTEXT
	PVOID m_pContext;

} SFileProcCreateContext;

#define DEF_FILEPROC_COMMAND_DELETE_CONTEXT (2)
typedef struct SFileProcDeleteContext
{
	// This field you provided when handle DEF_FILEPROC_COMMAND_CREATE_CONTEXT (see SFileProcCreateContext)
	PVOID m_pContext;

} SFileProcDeleteContext;

#define DEF_FILEPROC_COMMAND_READ (3)
typedef struct SFileProcRead
{
	// This field you provided when handle DEF_FILEPROC_COMMAND_CREATE_CONTEXT (see SFileProcCreateContext)
	PVOID m_pContext;

	LPVOID m_pBuffer;
	DWORD m_dwBufferSize;
	DWORD m_nReadBytes;
	BOOL m_bRes;

} SFileProcRead;

#define DEF_FILEPROC_COMMAND_WRITE (4)
typedef struct SFileProcWrite
{
	// This field you provided when handle DEF_FILEPROC_COMMAND_CREATE_CONTEXT (see SFileProcCreateContext)
	PVOID m_pContext;

	LPCVOID m_pBuffer;
	DWORD m_dwBufferSize;
	DWORD m_nWrittenBytes;
	BOOL m_bRes;

} SFileProcWrite;

#define DEF_FILEPROC_COMMAND_SEEK (5)
typedef struct SFileProcSeek
{
	// This field you provided when handle DEF_FILEPROC_COMMAND_CREATE_CONTEXT (see SFileProcCreateContext)
	PVOID m_pContext;

	LARGE_INTEGER m_Distance;
	DWORD m_dwMoveMethod;
	LARGE_INTEGER m_NewPos;
	BOOL m_bRes;

} SFileProcSeek;

#define DEF_FILEPROC_COMMAND_GETSIZE (6)
typedef struct SFileProcGetSize
{
	// This field you provided when handle DEF_FILEPROC_COMMAND_CREATE_CONTEXT (see SFileProcCreateContext)
	PVOID m_pContext;

	LARGE_INTEGER m_Size;

} SFileProcGetSize;

// Virtual registry

#ifdef UNICODE
#define BoxedAppSDK_CreateVirtualRegKey BoxedAppSDK_CreateVirtualRegKeyW
#else
#define BoxedAppSDK_CreateVirtualRegKey BoxedAppSDK_CreateVirtualRegKeyA
#endif // UNICODE

LONG BOXEDAPPSDKAPI BoxedAppSDK_CreateVirtualRegKeyA(
	HKEY hKey,
	LPCSTR lpSubKey,
	DWORD Reserved,
	LPCSTR lpClass,
	DWORD dwOptions,
	REGSAM samDesired,
	LPSECURITY_ATTRIBUTES lpSecurityAttributes,
	PHKEY phkResult,
	LPDWORD lpdwDisposition
);

LONG BOXEDAPPSDKAPI BoxedAppSDK_CreateVirtualRegKeyW(
	HKEY hKey,
	LPCWSTR lpSubKey,
	DWORD Reserved,
	LPCWSTR lpClass,
	DWORD dwOptions,
	REGSAM samDesired,
	LPSECURITY_ATTRIBUTES lpSecurityAttributes,
	PHKEY phkResult,
	LPDWORD lpdwDisposition
);

void BOXEDAPPSDKAPI BoxedAppSDK_SetContext(LPCSTR szContext);

DWORD BOXEDAPPSDKAPI BoxedAppSDK_RegisterCOMLibraryInVirtualRegistryA(LPCSTR szVirtualFilePath);
DWORD BOXEDAPPSDKAPI BoxedAppSDK_RegisterCOMLibraryInVirtualRegistryW(LPCWSTR szVirtualFilePath);

#ifdef UNICODE
#define BoxedAppSDK_RegisterCOMLibraryInVirtualRegistry BoxedAppSDK_RegisterCOMLibraryInVirtualRegistryW
#else
#define BoxedAppSDK_RegisterCOMLibraryInVirtualRegistry BoxedAppSDK_RegisterCOMLibraryInVirtualRegistryA
#endif // UNICODE

void BOXEDAPPSDKAPI BoxedAppSDK_EnableOption(DWORD dwOptionIndex, BOOL bEnable);
BOOL BOXEDAPPSDKAPI BoxedAppSDK_IsOptionEnabled(DWORD dwOptionIndex);

typedef enum _ENUM_BOXEDAPPSDK_REQUEST_ID
{
	EnumBoxedAppSDK_RequestId__RegQueryValue = 1, 
	EnumBoxedAppSDK_RequestId__RedirectFilePath = 2

} ENUM_BOXEDAPPSDK_REQUEST_ID;

typedef DWORD (BOXEDAPPSDKAPI *PBOXEDAPPHANDLER)(PVOID Param, ENUM_BOXEDAPPSDK_REQUEST_ID RequestId, PVOID pAdditionalInfo);
DWORD BOXEDAPPSDKAPI BoxedAppSDK_AddHandler(PBOXEDAPPHANDLER pHandler, PVOID Param);
BOOL BOXEDAPPSDKAPI BoxedAppSDK_RemoveHandler(DWORD dwHandlerId);

struct SBoxedAppSDK__RegQueryValue
{
	// in
	HKEY m_Root;
	LPCWSTR m_szPath;
	LPCWSTR m_szValue;

	// out
	BOOL m_bHandled;

	DWORD m_dwType;
	PVOID m_pData;
	DWORD m_dwSize;
};

struct SBoxedAppSDK__RedirectFilePath
{
	// in
	LPCWSTR m_szPath;

	// out
	BOOL m_bHandled;

	LPWSTR m_szRedirectToPath;
};

PVOID BOXEDAPPSDKAPI BoxedAppSDK_Alloc(DWORD dwSize);
BOOL BOXEDAPPSDKAPI BoxedAppSDK_Free(PVOID pData);

DWORD BOXEDAPPSDKAPI BoxedAppSDK_DeleteFileInVirtualFileSystemW(LPCWSTR szPath);
DWORD BOXEDAPPSDKAPI BoxedAppSDK_DeleteFileInVirtualFileSystemA(LPCSTR szPath);

#ifdef UNICODE
#define BoxedAppSDK_DeleteFileInVirtualFileSystem BoxedAppSDK_DeleteFileInVirtualFileSystemW
#else
#define BoxedAppSDK_DeleteFileInVirtualFileSystem BoxedAppSDK_DeleteFileInVirtualFileSystemA
#endif // UNICODE

BOOL BOXEDAPPSDKAPI BoxedAppSDK_CreateProcessFromMemoryA(
	LPCVOID pBuffer, 
	DWORD dwSize, 

	LPCSTR lpApplicationName,
	LPSTR lpCommandLine,
	LPSECURITY_ATTRIBUTES lpProcessAttributes,
	LPSECURITY_ATTRIBUTES lpThreadAttributes,
	BOOL bInheritHandles,
	DWORD dwCreationFlags,
	LPVOID lpEnvironment,
	LPCSTR lpCurrentDirectory,
	LPSTARTUPINFOA lpStartupInfo,
	LPPROCESS_INFORMATION lpProcessInformation
);

BOOL BOXEDAPPSDKAPI BoxedAppSDK_CreateProcessFromMemoryW(
	LPCVOID pBuffer, 
	DWORD dwSize, 

	LPCWSTR lpApplicationName,
	LPWSTR lpCommandLine,
	LPSECURITY_ATTRIBUTES lpProcessAttributes,
	LPSECURITY_ATTRIBUTES lpThreadAttributes,
	BOOL bInheritHandles,
	DWORD dwCreationFlags,
	LPVOID lpEnvironment,
	LPCWSTR lpCurrentDirectory,
	LPSTARTUPINFOW lpStartupInfo,
	LPPROCESS_INFORMATION lpProcessInformation
);

#ifdef UNICODE
#define BoxedAppSDK_CreateProcessFromMemory BoxedAppSDK_CreateProcessFromMemoryW
#else
#define BoxedAppSDK_CreateProcessFromMemory BoxedAppSDK_CreateProcessFromMemoryA
#endif // UNICODE

// Set param #0
void BOXEDAPPSDKAPI BoxedAppSDK_SetParam0(LPCSTR param);

// Create a virtual file based on IStream
HANDLE BOXEDAPPSDKAPI BoxedAppSDK_CreateVirtualFileBasedOnIStreamA(
	LPCSTR szPath, 
	DWORD dwDesiredAccess,
	DWORD dwShareMode,
	LPSECURITY_ATTRIBUTES lpSecurityAttributes,
	DWORD dwCreationDisposition,
	DWORD dwFlagsAndAttributes,
	HANDLE hTemplateFile, 

	LPSTREAM pStream
);

HANDLE BOXEDAPPSDKAPI BoxedAppSDK_CreateVirtualFileBasedOnIStreamW(
	LPCWSTR szPath, 
	DWORD dwDesiredAccess,
	DWORD dwShareMode,
	LPSECURITY_ATTRIBUTES lpSecurityAttributes,
	DWORD dwCreationDisposition,
	DWORD dwFlagsAndAttributes,
	HANDLE hTemplateFile, 

	LPSTREAM pStream
);

#ifdef UNICODE
#define BoxedAppSDK_CreateVirtualFileBasedOnIStream BoxedAppSDK_CreateVirtualFileBasedOnIStreamW
#else
#define BoxedAppSDK_CreateVirtualFileBasedOnIStream BoxedAppSDK_CreateVirtualFileBasedOnIStreamA
#endif // UNICODE

HANDLE BOXEDAPPSDKAPI BoxedAppSDK_CreateVirtualFileBasedOnBufferA(
	LPCSTR szPath, 
	DWORD dwDesiredAccess,
	DWORD dwShareMode,
	LPSECURITY_ATTRIBUTES lpSecurityAttributes,
	DWORD dwCreationDisposition,
	DWORD dwFlagsAndAttributes,
	HANDLE hTemplateFile, 

	PVOID pData, DWORD dwSize
);

HANDLE BOXEDAPPSDKAPI BoxedAppSDK_CreateVirtualFileBasedOnBufferW(
	LPCWSTR szPath, 
	DWORD dwDesiredAccess,
	DWORD dwShareMode,
	LPSECURITY_ATTRIBUTES lpSecurityAttributes,
	DWORD dwCreationDisposition,
	DWORD dwFlagsAndAttributes,
	HANDLE hTemplateFile, 

	PVOID pData, DWORD dwSize
);

#ifdef UNICODE
#define BoxedAppSDK_CreateVirtualFileBasedOnBuffer BoxedAppSDK_CreateVirtualFileBasedOnBufferW
#else
#define BoxedAppSDK_CreateVirtualFileBasedOnBuffer BoxedAppSDK_CreateVirtualFileBasedOnBufferA
#endif // UNICODE

// Attach BoxedApp SDK to another process
BOOL BOXEDAPPSDKAPI BoxedAppSDK_AttachToProcess(HANDLE hProcess);
// Detach BoxedApp SDK from a process
BOOL BOXEDAPPSDKAPI BoxedAppSDK_DetachFromProcess(HANDLE hProcess);

#ifdef __cplusplus
}
#endif

#include <poppack.h>

#endif // !__BOXEDAPPSDK_H__
