I am making a program to set those attributes with C++. With IDA, I find that lxcore.sys driver uses ZwSetEaFile() and LxssManager.dll uses NtSetEaFile() function to set NTFS extended attributes. Here are the functions mentioned in ntdl.dll (using IDA v7):


Here is the Microsoft documentation of ZwSetEaFile():

  _In_  HANDLE           FileHandle,
  _Out_ PIO_STATUS_BLOCK IoStatusBlock,
  _In_  PVOID            Buffer,
  _In_  ULONG            Length

But I'm not sure which one is appropriate to use? Is there any difference between them using in a user mode software?

2 Answers 2


There is no difference at the user mode level. The difference only exists when called from kernel mode in how the function arguments are passed in whether the parameters are guaranteed valid (Zw) or whether they should be verified (Nt). This documentation from Microsoft may shed some more light.


the op appears to have deleted some questions he posed as comments and accepted an answer
so this answer might appear to be not relevant to the present context

op commented if one could call the api in user_mode without loading ntdll.dll
or calling either of the two variants of the api viz NtSetEaFile or ZwSetEaFile

this answer shows how that can be done
the syscall number belongs to win7 sp1 32 bit
on compiling and executing a 0 byte text file will be created
whose extended info can be checked with ladislav zezulas filetest utility or by checking the ntfs usn change records

#include <windows.h>
#include <winternl.h>
typedef struct _MYEABUFF {
    ULONG neoff; UCHAR flg; UCHAR nlen; USHORT vlen; char eaname[0x100];
}MyEaBuff, *PMyEaBuff;
int main() {
    HANDLE fhand = CreateFileA("testec.txt", GENERIC_READ | GENERIC_WRITE,
    const char *Eaname="EATEST";const char *EaValue="This is the text For EATEST";
    UCHAR nlen=(UCHAR)strlen(Eaname);USHORT EaValueLen=(USHORT)strlen(EaValue);
    IO_STATUS_BLOCK iosb ={0}; MyEaBuff Buff ={0};
    Buff.neoff = 0; Buff.flg = 0; Buff.nlen = nlen; Buff.vlen = EaValueLen;
    strcpy_s(Buff.eaname, nlen + 1, Eaname);
    strcpy_s(Buff.eaname + nlen + 1, EaValueLen + 1, EaValue);
    PVOID iosb_ptr = &iosb; PVOID Buff_ptr = &Buff;
    __asm {
        push 108h
        push Buff_ptr
        push iosb_ptr
        push fhand
        call ntseaf
        jmp exit
    __asm {
        mov eax, 142h
        mov edx, 7ffe0300h
        call dword ptr ds : [edx]
        retn 4
    return 0;

result of the bin checked with cjdump.exe (old msdn mag code)

C:\testea>cl /nologo testea.cpp


C:\testea>CJDump.exe | grep testec.txt
Usn(0x0000000129433C28) Reason(0x00000100) testec.txt < USN_REASON_FILE_CREATE
Usn(0x0000000129433C78) Reason(0x00000500) testec.txt < USN_REASON_EA_CHANGE|0x100
Usn(0x0000000129433CC8) Reason(0x80000500) testec.txt < USN_REASON_CLOSE|0x500

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.