//This program creates an empty file using the
//NtCreateFile function of Windows NT's Native API.
//
//Note that this function is documented in the
//Windows DDK.
//
#include <Windows.h>
#include <Ntsecapi.h> //for PUNICODE_STRING
#include <iostream>

using namespace std;


//NT Native API declarations
typedef LONG NTSTATUS;

typedef struct _IO_STATUS_BLOCK {
    union {
        NTSTATUS Status;
        PVOID Pointer;
    };

    ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;

typedef struct _OBJECT_ATTRIBUTES {
    ULONG Length;
    HANDLE RootDirectory;
    PUNICODE_STRING ObjectName;
    ULONG Attributes;
    PVOID SecurityDescriptor;
    PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;

typedef enum _CREATE_DISPOSITION {
    FILE_SUPERSEDE                  =0x00000000,
    FILE_OPEN                       =0x00000001,
    FILE_CREATE                     =0x00000002,
    FILE_OPEN_IF                    =0x00000003,
    FILE_OVERWRITE                  =0x00000004,
    FILE_OVERWRITE_IF               =0x00000005,
    FILE_MAXIMUM_DISPOSITION        =0x00000005
} CREATE_DISPOSITION;

// Valid values for the Attributes field of OBJECT_ATTRIBUTES

#define OBJ_INHERIT             0x00000002L
#define OBJ_PERMANENT           0x00000010L
#define OBJ_EXCLUSIVE           0x00000020L
#define OBJ_CASE_INSENSITIVE    0x00000040L
#define OBJ_OPENIF              0x00000080L
#define OBJ_OPENLINK            0x00000100L
#define OBJ_KERNEL_HANDLE       0x00000200L
#define OBJ_FORCE_ACCESS_CHECK  0x00000400L
#define OBJ_VALID_ATTRIBUTES    0x000007F2L

#define FILE_ATTRIBUTE_NORMAL               0x00000080

#define NT_SUCCESS(Status) ((long)(Status) >= 0)

typedef NTSTATUS __stdcall NtCreateFile(PHANDLE FileHandle, 
                                        ACCESS_MASK DesiredAccess, 
                                        POBJECT_ATTRIBUTES ObjectAttributes, 
                                        PIO_STATUS_BLOCK IoStatusBlock, 
                                        PLARGE_INTEGER AllocationSize,
                                        ULONG FileAttributes, 
                                        ULONG ShareAccess, 
                                        ULONG CreateDisposition, 
                                        ULONG CreateOptions, 
                                        PVOID EaBuffer, 
                                        ULONG EaLength );

typedef VOID __stdcall RtlInitUnicodeString(PUNICODE_STRING  DestinationString, 
                                            PCWSTR  SourceString);

//Small demo program that creates a file using the Windows Native API
int main(int argc, char *argv[])
{
    //Dynamically load ntdll.dll and find out the addresses of 
    //NtCreateFile and RtlInitUnicodeString
    HMODULE hMod= LoadLibrary("ntdll.dll");
    if (! hMod)
    {
        cerr << "Could not load ntdll.dll" << endl;
        exit(1);
    }

    NtCreateFile *pNtCreateFile;
    RtlInitUnicodeString *pRtlInitUnicodeString;
    pNtCreateFile= (NtCreateFile*) GetProcAddress(hMod, "NtCreateFile");
    pRtlInitUnicodeString= (RtlInitUnicodeString*) GetProcAddress(hMod, "RtlInitUnicodeString");

    //Prepare all arguments for the call to NtCreateFile
    IO_STATUS_BLOCK ioStatus;
    memset(&ioStatus, 0, sizeof(ioStatus));

    OBJECT_ATTRIBUTES object;
    memset(&object, 0, sizeof(object));
    object.Length= sizeof(object);
    object.Attributes= OBJ_CASE_INSENSITIVE;

    UNICODE_STRING fn;
    pRtlInitUnicodeString(&fn, L"\\??\\C:\\testfile.txt");
    object.ObjectName= &fn;

    //Finally, create the file C:\testfile.txt. 
    //If the file already exists, it is truncated.
    HANDLE out;
    NTSTATUS status;
    status= pNtCreateFile(&out, GENERIC_WRITE, &object, &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL, 
        0, FILE_CREATE, 0, NULL, 0);

    if (! NT_SUCCESS(status))
    {
        cerr << "Could not create file." << endl;
        exit(1);
    }
    else
        cerr << "Successfully created the file." << endl;


    return 1;
}
