Valid HTML 4.01 Transitional Valid CSS Valid SVG 1.0

Me, myself & IT

Extended (Directory & File) Attributes

Purpose
Background Information
Native API Implementation

Purpose

Present implementations of GetExtendedFileAttributesW() and SetExtendedFileAttributesW() functions for Microsoft® Windows NT to get, set and remove extended (file & directory) attributes.

Background Information

Extended (directory & file) attributes (a legacy from OS/2) are name/value pairs, with names of up to 255 printable extended (upper-case) ASCII characters except ", *, +, ,, /, :, ;, <, >, ?, =, [, \, ] plus |, and values of up to 65535 bytes. They are stored with files as well as directories on FAT-12, FAT-16 and NTFS file systems (mutually exclusive with the latter’s reparse points) and not supported by the Win32 API!

Note: the Win32 functions CopyFileEx() and CreateFile() provide only indirect support for extended attributes.

The MSDN article Creating and Opening Files specifies:

An application creating a new file can supply an optional handle to a template file, from which CreateFile takes file attributes and extended attributes for creation of the new file.
The MSDN article File Attribute Constants specifies:
File attributes are metadata values stored by the file system on disk and are used by the system and are available to developers via various file I/O APIs.

[…]

Constant/value Description
FILE_ATTRIBUTE_EA
262144 (0x00040000)
A file or directory with extended attributes.

IMPORTANT: This constant is for internal use only.

FILE_ATTRIBUTE_RECALL_ON_OPEN
262144 (0x00040000)
This attribute only appears in directory enumeration classes (FILE_DIRECTORY_INFORMATION, FILE_BOTH_DIR_INFORMATION, etc.). When this attribute is set, it means that the file or directory has no physical representation on the local system; the item is virtual. Opening the item will be more expensive than normal, e.g. it will cause at least some of it to be fetched from a remote store.
OOPS: both constants have the same numerical value!

Finally see the MSDN articles Kernel Extended Attributes and File Permissions for WSL.

Native API Implementation

Perform the following 3 simple steps to build a combined import and object library for the GetExtendedFileAttributeW() and SetExtendedFileAttributeW() functions, implemented with Windows NT’s native API provided by NTDLL.dll.
  1. Create the text file ext-attr.c with the following content in an arbitrary, preferable empty directory:

    // Copyright © 2004-2025, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    #ifndef _DLL
    #pragma comment(compiler)
    #pragma comment(lib, "ext-attr")
    
    #pragma intrinsic(__movsb, strlen)
    
    #define STRICT
    #define UNICODE
    #define WIN32_LEAN_AND_MEAN
    
    #include <windows.h>
    
    #define FILE_SHARE_NONE			0UL
    #define FILE_OPEN			1UL
    #define FILE_OPENED			1UL
    #define FILE_CREATE			2UL
    #define FILE_CREATED			2UL
    #define FILE_OPEN_IF			3UL
    #define FILE_SYNCHRONOUS_IO_NONALERT	0x00000020UL
    #define FILE_OPEN_FOR_BACKUP_INTENT	0x00004000UL
    
    #define OBJ_CASE_INSENSITIVE	64UL
    
    #define STATUS_SUCCESS			0L
    #define STATUS_BUFFER_OVERFLOW		0x80000005L	// ERROR_MORE_DATA
    #define STATUS_NO_MORE_EAS		0x80000012L	// ERROR_NO_MORE_ITEMS
    #define STATUS_INVALID_EA_NAME		0x80000013L	// ERROR_INVALID_EA_NAME
    #define STATUS_EA_LIST_INCONSISTENT	0x80000014L	// ERROR_EA_LIST_INCONSISTENT
    #define STATUS_INVALID_EA_FLAG		0x80000015L	// ERROR_EA_LIST_INCONSISTENT
    #define STATUS_BUFFER_TOO_SMALL		0xC0000023L	// ERROR_INSUFFICIENT_BUFFER
    #define STATUS_EAS_NOT_SUPPORTED	0xC000004FL	// ERROR_EAS_NOT_SUPPORTED
    #define STATUS_EA_TOO_LARGE		0xC0000050L	// ERROR_EA_LIST_INCONSISTENT
    #define STATUS_NONEXISTENT_EA_ENTRY	0xC0000051L	// ERROR_FILE_CORRUPT
    #define STATUS_NO_EAS_ON_FILE		0xC0000052L	// ERROR_FILE_CORRUPT
    #define STATUS_EA_CORRUPT_ERROR		0xC0000053L	// ERROR_FILE_CORRUPT
    #define STATUS_INSUFFICIENT_RESOURCES	0xC000009AL	// ERROR_NO_SYSTEM_RESOURCES
    
    typedef	LONG	NTSTATUS;
    
    typedef	enum	_FILE_INFORMATION_CLASS
    {
    	FileEaInformation     = 7,
    	FileFullEaInformation = 15
    } FILE_INFORMATION_CLASS;
    
    typedef	struct	_FILE_EA_INFORMATION
    {
    	DWORD	EaSize;
    } FILE_EA_INFORMATION;
    
    #pragma pack(push, 1)
    
    typedef	struct	_FILE_GET_EA_INFORMATION
    {
    	DWORD	NextEntryOffset;
    	BYTE	EaNameLength;
    	CHAR	EaName[256];
    } FILE_GET_EA_INFORMATION;
    
    typedef	struct	_FILE_FULL_EA_INFORMATION
    {
    	DWORD	NextEntryOffset;
    	BYTE	Flags;
    	BYTE	EaNameLength;
    	WORD	EaValueLength;
    	CHAR	EaName[1];
    //	BYTE	EaValue[1];
    } FILE_FULL_EA_INFORMATION;
    
    #pragma pack(pop)
    
    typedef	struct	_UNICODE_STRING
    {
    	WORD	Length;
    	WORD	MaximumLength;
    	LPWSTR	Buffer;
    } UNICODE_STRING;
    
    typedef	struct	_OBJECT_ATTRIBUTES
    {
    	DWORD		Length;
    	HANDLE		RootDirectory;
    	UNICODE_STRING	*ObjectName;
    	DWORD		Attributes;
    	LPVOID		SecurityDescriptor;
    	LPVOID		SecurityQualityOfService;
    } OBJECT_ATTRIBUTES;
    
    typedef	struct	_IO_STATUS_BLOCK
    {
    	union
    	{
    		LONG	Status;
    		LPVOID	Pointer;
    	};
    	DWORD_PTR	Information;
    } IO_STATUS_BLOCK;
    
    typedef	struct	_RTLP_CURDIR_REF
    {
    	LONG	RefCount;
    	HANDLE	Handle;
    } RTLP_CURDIR_REF;
    
    typedef	struct	_RTL_RELATIVE_NAME_U
    {
    	UNICODE_STRING	RelativeName;
    	HANDLE		ContainingDirectory;
    	RTLP_CURDIR_REF	*CurDirRef;
    } RTL_RELATIVE_NAME_U;
    
    typedef	struct	_RTL_USER_PROCESS_PARAMETERS
    {
    	BYTE		Reserved1[16];
    	LPVOID		Reserved2[10];
    	UNICODE_STRING	ImagePathName;
    	UNICODE_STRING	CommandLine;
    } RTL_USER_PROCESS_PARAMETERS;
    
    typedef	struct	_PEB_LDR_DATA
    {
    	BYTE		Reserved1[8];
    	LPVOID		Reserved2[3];
    	LIST_ENTRY	InMemoryOrderModuleList;
    } PEB_LDR_DATA;
    
    typedef	VOID	(NTAPI	PS_POST_PROCESS_INIT_ROUTINE) (VOID);
    
    typedef	struct	_PEB
    {
    	BYTE				Reserved1[2];
    	BOOLEAN				BeingDebugged;
    	BYTE				Reserved2[1];
    	LPVOID				Reserved3[2];
    	PEB_LDR_DATA			*Ldr;
    	RTL_USER_PROCESS_PARAMETERS	*ProcessParameters;
    #if 0
    	LPVOID				Reserved4[3];
    #else
    	LPVOID				SubSystemData;
    	HANDLE				ProcessHeap;
    	RTL_CRITICAL_SECTION		*FastPebLock;
    #endif
    	LPVOID				AtlThunkSListPtr;
    	LPVOID				Reserved5;
    	DWORD				Reserved6;
    	LPVOID				Reserved7;
    	DWORD				Reserved8;
    	DWORD				AtlThunkSListPtr32;
    	LPVOID				Reserved9[45];
    	BYTE				Reserved10[96];
    	PS_POST_PROCESS_INIT_ROUTINE	*PostProcessInitRoutine;
    	BYTE				Reserved11[128];
    	LPVOID				Reserved12[1];
    	DWORD				SessionId;
    } PEB;
    
    typedef	struct	_TEB
    {
    	LPVOID		Reserved1[12];
    	PEB		*ProcessEnvironmentBlock;
    	LPVOID		Reserved2[399];
    	BYTE		Reserved3[1952];
    	LPVOID		TlsSlots[64];
    	LIST_ENTRY	TlsLinks;
    	LPVOID		Reserved5[26];
    	LPVOID		ReservedForOle;
    	LPVOID		Reserved6[4];
    	LPVOID		*TlsExpansionSlots;
    } TEB;
    
    __declspec(dllimport)
    LONG	NTAPI	NtClose(HANDLE Handle);
    
    __declspec(dllimport)
    LONG	NTAPI	NtCreateFile(HANDLE                   *FileHandle,
    		             ACCESS_MASK              DesiredAccess,
    		             OBJECT_ATTRIBUTES        *ObjectAttributes,
    		             IO_STATUS_BLOCK          *IoStatusBlock,
    		             LARGE_INTEGER            *AllocationSize,
    		             DWORD                    FileAttributes,
    		             DWORD                    ShareAccess,
    		             DWORD                    CreateDisposition,
    		             DWORD                    CreateOptions,
    		             FILE_FULL_EA_INFORMATION *EaBuffer,
    		             DWORD                    EaLength);
    __declspec(dllimport)
    LONG	NTAPI	NtOpenFile(HANDLE            *FileHandle,
    		           ACCESS_MASK       DesiredAccess,
    		           OBJECT_ATTRIBUTES *ObjectAttributes,
    		           IO_STATUS_BLOCK   *IoStatusBlock,
    		           DWORD             ShareAccess,
    		           DWORD             OpenOptions);
    __declspec(dllimport)
    LONG	NTAPI	NtQueryEaFile(HANDLE                   FileHandle,
    		              IO_STATUS_BLOCK          *IoStatusBlock,
    		              FILE_FULL_EA_INFORMATION *EaBuffer,
    		              DWORD                    EaBufferLength,
    		              BOOLEAN                  ReturnSingleEntry,
    		              FILE_GET_EA_INFORMATION  *EaList,
    		              DWORD                    EaListLength,
    		              LPDWORD                  EaIndex,
    		              BOOLEAN                  RestartScan);
    __declspec(dllimport)
    LONG	NTAPI	NtQueryInformationFile(HANDLE                 FileHandle,
    		                       IO_STATUS_BLOCK        *IoStatusBlock,
    		                       VOID                   *FileInformation,
    		                       DWORD                  FileInformationLength,
    		                       FILE_INFORMATION_CLASS FileInformationClass);
    __declspec(dllimport)
    LONG	NTAPI	NtSetEaFile(HANDLE          FileHandle,
    		            IO_STATUS_BLOCK *IoStatusBlock,
    		            VOID            *Buffer,
    		            DWORD           Length);
    __declspec(dllimport)
    LONG	NTAPI	NtSetInformationFile(HANDLE                 FileHandle,
    		                     IO_STATUS_BLOCK        *IoStatusBlock,
    		                     VOID                   *FileInformation,
    		                     DWORD                  FileInformationLength,
    		                     FILE_INFORMATION_CLASS FileInformationClass);
    __declspec(dllimport)
    LPVOID	NTAPI	RtlAllocateHeap(LPCVOID HeapHandle,
    		                DWORD   Flags,
    		                SIZE_T  Size);
    __declspec(dllimport)
    LONG	NTAPI	RtlDosPathNameToNtPathName_U_WithStatus(LPCWSTR             DosName,
    		                                        UNICODE_STRING      *NtName,
    		                                        LPCWSTR             *PartName,
    		                                        RTL_RELATIVE_NAME_U *RelativeName);
    __declspec(dllimport)
    BOOL	NTAPI	RtlFreeHeap(LPCVOID HeapHandle,
    		            DWORD   Flags,
    		            LPCVOID HeapBase);
    __declspec(dllimport)
    VOID	NTAPI	RtlFreeUnicodeString(UNICODE_STRING *UnicodeString);
    
    __declspec(dllimport)
    VOID	NTAPI	RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS Status);
    
    BOOL	WINAPI	FreeExtendedFileAttributes(LPCVOID lpBlock)
    {
    	LPCVOID	lpHeap = NtCurrentTeb()->ProcessEnvironmentBlock->ProcessHeap;
    	LONG	ntStatus = STATUS_INVALID_PARAMETER;
    
    	if (lpBlock != NULL)
    		return RtlFreeHeap(lpHeap, 0UL, lpBlock);
    
    	RtlSetLastWin32ErrorAndNtStatusFromNtStatus(ntStatus);
    
    	return FALSE;
    }
    
    LPCVOID	WINAPI	GetExtendedFileAttributesW(LPCWSTR lpSource)
    {
    	LPCVOID	lpHeap = NtCurrentTeb()->ProcessEnvironmentBlock->ProcessHeap;
    	LONG	ntStatus = STATUS_INVALID_PARAMETER;
    	DWORD	dwSource;
    	HANDLE	hSource;
    
    	IO_STATUS_BLOCK		ioSource;
    	UNICODE_STRING		usSource;
    	OBJECT_ATTRIBUTES	oaSource = {sizeof(oaSource),
    				            (HANDLE) NULL,
    				            (UNICODE_STRING *) NULL,
    				            OBJ_CASE_INSENSITIVE,
    				            NULL,
    				            NULL};
    
    	FILE_FULL_EA_INFORMATION	*eaSource = NULL;
    
    	if (lpSource != NULL && *lpSource != L'\0')
    	{
    		ntStatus = RtlDosPathNameToNtPathName_U_WithStatus(lpSource,
    		                                                   &usSource,
    		                                                   (LPCWSTR *) NULL,
    		                                                   NULL);
    		if (ntStatus == STATUS_SUCCESS)
    		{
    			oaSource.ObjectName = &usSource;
    
    			ntStatus = NtOpenFile(&hSource,
    			                      FILE_READ_EA | SYNCHRONIZE,
    			                      &oaSource,
    			                      &ioSource,
    			                      FILE_SHARE_NONE,
    			                      FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT);
    
    			RtlFreeUnicodeString(&usSource);
    
    			if (ntStatus == STATUS_SUCCESS)
    			{
    				ntStatus = NtQueryInformationFile(hSource,
    				                                  &ioSource,
    				                                  &dwSource,
    				                                  sizeof(dwSource),
    				                                  FileEaInformation);
    				if (ntStatus == STATUS_SUCCESS)
    					if (dwSource == 0UL)
    						ntStatus = STATUS_NO_EAS_ON_FILE;
    					else
    					{
    #if 0 // CAVEAT: NtQueryInformationFile() returns for FileEaInformation
          //          a value (number of EAs - 1) * 4 lower than the buffer size!
    
    						eaSource = RtlAllocateHeap(lpHeap, 0UL, dwSource);
    #else
    						eaSource = RtlAllocateHeap(lpHeap, 0UL, dwSource = 65536UL);
    #endif
    						if (eaSource == NULL)
    							ntStatus = STATUS_INSUFFICIENT_RESOURCES;
    						else
    						{
    #if 0 // CAVEAT: NtQueryInformationFile() fails with STATUS_NOT_IMPLEMENTED for FileFullEaInformation!
    
    							ntStatus = NtQueryInformationFile(hSource,
    							                                  &ioSource,
    							                                  eaSource,
    							                                  dwSource,
    							                                  FileFullEaInformation);
    #else
    							ntStatus = NtQueryEaFile(hSource,
    							                         &ioSource,
    							                         eaSource,
    							                         dwSource,
    							                         FALSE,
    							                         (FILE_GET_EA_INFORMATION *) NULL,
    							                         0UL,
    							                         (LPDWORD) NULL,
    							                         TRUE);
    #endif
    							if (ntStatus != STATUS_SUCCESS)
    							{
    								RtlFreeHeap(lpHeap, 0UL, eaSource);
    
    								eaSource = NULL;
    							}
    						}
    					}
    
    				NtClose(hSource);
    			}
    		}
    	}
    
    	if (eaSource == NULL)
    		RtlSetLastWin32ErrorAndNtStatusFromNtStatus(ntStatus);
    
    	return eaSource;
    }
    
    __declspec(safebuffers)
    DWORD	WINAPI	GetExtendedFileAttributeW(LPCWSTR lpSource,
    		                          LPCSTR  lpEaName,
    		                          LPVOID  lpEaValue,
    		                          DWORD   dwEaValue)
    {
    	LPCVOID	lpHeap = NtCurrentTeb()->ProcessEnvironmentBlock->ProcessHeap;
    	LONG	ntStatus = STATUS_INVALID_PARAMETER;
    	DWORD	dwEaName;
    	DWORD	dwSource = 0UL;
    	HANDLE	hSource;
    
    	IO_STATUS_BLOCK		ioSource;
    	UNICODE_STRING		usSource;
    	OBJECT_ATTRIBUTES	oaSource = {sizeof(oaSource),
    				            (HANDLE) NULL,
    				            (UNICODE_STRING *) NULL,
    				            OBJ_CASE_INSENSITIVE,
    				            NULL,
    				            NULL};
    
    	FILE_GET_EA_INFORMATION		eaQuery;
    	FILE_FULL_EA_INFORMATION	*eaSource;
    
    	if (lpSource != NULL && *lpSource != L'\0'
    	 && lpEaName != NULL && *lpEaName != '\0'
    	 && (dwEaName = strlen(lpEaName)) < 256UL
    	 && (dwEaValue == 0UL || dwEaValue != 0UL && lpEaValue != NULL))
    	{
    		ntStatus = RtlDosPathNameToNtPathName_U_WithStatus(lpSource,
    		                                                   &usSource,
    		                                                   (LPCWSTR *) NULL,
    		                                                   NULL);
    		if (ntStatus == STATUS_SUCCESS)
    		{
    			oaSource.ObjectName = &usSource;
    
    			ntStatus = NtOpenFile(&hSource,
    			                      FILE_READ_EA | SYNCHRONIZE,
    			                      &oaSource,
    			                      &ioSource,
    			                      FILE_SHARE_NONE,
    			                      FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT);
    
    			RtlFreeUnicodeString(&usSource);
    
    			if (ntStatus == STATUS_SUCCESS)
    			{
    				eaSource = RtlAllocateHeap(lpHeap, 0UL, 65536UL);
    
    				if (eaSource == NULL)
    					ntStatus = STATUS_INSUFFICIENT_RESOURCES;
    				else
    				{
    					eaQuery.NextEntryOffset = 0UL;
    					eaQuery.EaNameLength = (BYTE) dwEaName;
    
    					__movsb(eaQuery.EaName, lpEaName, dwEaName + 1UL);
    
    					ntStatus = NtQueryEaFile(hSource,
    					                         &ioSource,
    					                         eaSource,
    					                         65536UL,
    					                         TRUE,
    					                         &eaQuery,
    					                         sizeof(eaQuery),
    					                         (LPDWORD) NULL,
    					                         TRUE);
    
    					if (ntStatus == STATUS_SUCCESS)
    					{
    						dwSource = eaSource->EaValueLength;
    
    						if (dwSource > dwEaValue)
    							ntStatus = STATUS_BUFFER_TOO_SMALL;
    						else if (dwSource == 0UL)
    							ntStatus = STATUS_NONEXISTENT_EA_ENTRY;
    						else if (lpEaValue != NULL)
    							__movsb(lpEaValue,
    							        eaSource->EaName + eaSource->EaNameLength + 1,
    							        eaSource->EaValueLength);
    					}
    
    					RtlFreeHeap(lpHeap, 0UL, eaSource);
    				}
    
    				NtClose(hSource);
    			}
    		}
    	}
    
    	if (dwSource == 0UL)
    		RtlSetLastWin32ErrorAndNtStatusFromNtStatus(ntStatus);
    
    	return dwSource;
    }
    
    BOOL	WINAPI	SetExtendedFileAttributeW(LPCWSTR lpTarget,
    		                          LPCSTR  lpEaName,
    		                          LPCVOID lpEaValue,
    		                          DWORD   dwEaValue)
    {
    	LPCVOID	lpHeap = NtCurrentTeb()->ProcessEnvironmentBlock->ProcessHeap;
    	LONG	ntStatus = STATUS_INVALID_PARAMETER;
    	DWORD	dwEaName;
    	DWORD	dwTarget;
    	BOOL	bTarget = FALSE;
    	HANDLE	hTarget;
    
    	IO_STATUS_BLOCK		ioTarget;
    	UNICODE_STRING		usTarget;
    	OBJECT_ATTRIBUTES	oaTarget = {sizeof(oaTarget),
    				            (HANDLE) NULL,
    				            (UNICODE_STRING *) NULL,
    				            OBJ_CASE_INSENSITIVE,
    				            NULL,
    				            NULL};
    
    	FILE_FULL_EA_INFORMATION	*eaTarget;
    
    	if (lpTarget != NULL && *lpTarget != L'\0'
    	 && lpEaName != NULL && *lpEaName != '\0'
    	 && (dwEaValue == 0UL || dwEaValue != 0UL && lpEaValue != NULL)
    	 && (dwEaName = strlen(lpEaName)) < 256UL
    	 && (dwTarget = sizeof(*eaTarget) + dwEaName + dwEaValue) < 65536UL)
    	{
    		eaTarget = RtlAllocateHeap(lpHeap, 0UL, dwTarget);
    
    		if (eaTarget == NULL)
    			ntStatus = STATUS_INSUFFICIENT_RESOURCES;
    		else
    		{
    			eaTarget->NextEntryOffset = 0UL;
    			eaTarget->Flags = 0;
    			eaTarget->EaNameLength = (BYTE) dwEaName;
    			eaTarget->EaValueLength = (WORD) dwEaValue;
    
    			__movsb(eaTarget->EaName, lpEaName, dwEaName + 1UL);
    			__movsb(eaTarget->EaName + dwEaName + 1UL, lpEaValue, dwEaValue);
    
    			ntStatus = RtlDosPathNameToNtPathName_U_WithStatus(lpTarget,
    			                                                   &usTarget,
    			                                                   (LPCWSTR *) NULL,
    			                                                   NULL);
    			if (ntStatus == STATUS_SUCCESS)
    			{
    				oaTarget.ObjectName = &usTarget;
    
    				ntStatus = NtCreateFile(&hTarget,
    				                        FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | SYNCHRONIZE,
    				                        &oaTarget,
    				                        &ioTarget,
    				                        (LARGE_INTEGER *) NULL,
    				                        FILE_ATTRIBUTE_NORMAL,
    				                        FILE_SHARE_NONE,
    				                        FILE_OPEN_IF,
    				                        FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
    				                        eaTarget,
    				                        dwTarget);
    
    				RtlFreeUnicodeString(&usTarget);
    
    				if (ntStatus == STATUS_SUCCESS)
    				{
    					if (ioTarget.Information == FILE_CREATED)
    						bTarget = TRUE;
    					else
    					{
    #if 0 // CAVEAT: NtSetInformationFile() fails with STATUS_INVALID_INFO_CLASS for FileFullEaInformation!
    
    						ntStatus = NtSetInformationFile(hTarget,
    						                                &ioTarget,
    						                                eaTarget,
    						                                dwTarget,
    						                                FileFullEaInformation);
    #else
    						ntStatus = NtSetEaFile(hTarget,
    						                       &ioTarget,
    						                       eaTarget,
    						                       dwTarget);
    #endif
    						if (ntStatus == STATUS_SUCCESS)
    							bTarget = TRUE;
    					}
    
    					NtClose(hTarget);
    				}
    			}
    
    			RtlFreeHeap(lpHeap, 0UL, eaTarget);
    		}
    	}
    
    	if (!bTarget)
    		RtlSetLastWin32ErrorAndNtStatusFromNtStatus(ntStatus);
    
    	return bTarget;
    }
    #else // _DLL
    __declspec(dllexport)
    long	NtClose(void *_1)
    { return 0; }
    
    __declspec(dllexport)
    long	NtCreateFile(void *_1, long _2, void *_3, void *_4, void *_5, long _6, long _7, long _8, long _9, void *_10, long _11)
    { return 0; }
    
    __declspec(dllexport)
    long	NtOpenFile(void *_1, long _2, void *_3, void *_4, long _5, long _6)
    { return 0; }
    
    __declspec(dllexport)
    long	NtQueryEaFile(void *_1, void *_2, void *_3, long _4, long _5, void *_6, long _7, void *_8, long _9)
    { return 0; }
    
    __declspec(dllexport)
    long	NtQueryInformationFile(void *_1, void *_2, void *_3, long _4, long _5)
    { return 0; }
    
    __declspec(dllexport)
    long	NtSetEaFile(void *_1, void *_2, void *_3, long _4)
    { return 0; }
    
    __declspec(dllexport)
    long	NtSetInformationFile(void *_1, void *_2, void *_3, long _4, long _5)
    { return 0; }
    
    __declspec(dllexport)
    void	*RtlAllocateHeap(void *_1, long _2, void *_3)
    { return 0; }
    
    __declspec(dllexport)
    long	RtlDosPathNameToNtPathName_U_WithStatus(void *_1, void *_2, void *_3, void *_4)
    { return 0; }
    
    __declspec(dllexport)
    long	RtlFreeHeap(void *_1, long _2, void *_3)
    { return 0; }
    
    __declspec(dllexport)
    void	RtlFreeUnicodeString(void *_1)
    {}
    
    __declspec(dllexport)
    void	RtlSetLastWin32ErrorAndNtStatusFromNtStatus(long _1)
    {}
    #endif // _DLL
  2. Compile the source file ext-attr.c created in step 1. a first time and build the import library ext-attr.lib from the generated object file ext-attr.obj:

    CL.EXE /c /Gz /MD /W4 /wd4100 /X /Zl ext-attr.c
    LINK.EXE /LIB /DEF /EXPORT:NtClose /EXPORT:NtCreateFile /EXPORT:NtOpenFile /EXPORT:NtQueryEaFile /EXPORT:NtQueryInformationFile /EXPORT:NtSetEaFile /EXPORT:NtSetInformationFile /EXPORT:RtlAllocateHeap /EXPORT:RtlDosPathNameToNtPathName_U_WithStatus /EXPORT:RtlFreeHeap /EXPORT:RtlFreeUnicodeString /EXPORT:RtlSetLastWin32ErrorAndNtStatusFromNtStatus /NAME:NTDLL /NODEFAULTLIB ext-attr.obj

    Note: the command lines can be copied and pasted as block into a Command Processor window.

    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    ext-attr.c
    
    Microsoft (R) Library Manager Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
       Creating library ext-attr.lib and object ext-attr.exp
  3. Compile the source file ext-attr.c created in step 1. a second time and put the generated object file ext-attr.obj into the import (as well as object) library ext-attr.lib built in step 2.:

    CL.EXE /c /Gy /Oxy /W4 /Zl ext-attr.c
    LINK.EXE /LIB /NODEFAULTLIB ext-attr.lib ext-attr.obj
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    ext-attr.c
    ext-attr.c(97) : warning C4201: nonstandard extension used : nameless struct/union
    
    Microsoft (R) Library Manager Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.

Contact and Feedback

If you miss anything here, have additions, comments, corrections, criticism or questions, want to give feedback, hints or tipps, report broken links, bugs, deficiencies, errors, inaccuracies, misrepresentations, omissions, shortcomings, vulnerabilities or weaknesses, …: don’t hesitate to contact me and feel free to ask, comment, criticise, flame, notify or report!

Use the X.509 certificate to send S/MIME encrypted mail.

Note: email in weird format and without a proper sender name is likely to be discarded!

I dislike HTML (and even weirder formats too) in email, I prefer to receive plain text.
I also expect to see your full (real) name as sender, not your nickname.
I abhor top posts and expect inline quotes in replies.

Terms and Conditions

By using this site, you signify your agreement to these terms and conditions. If you do not agree to these terms and conditions, do not use this site!

Data Protection Declaration

This web page records no (personal) data and stores no cookies in the web browser.

The web service is operated and provided by

Telekom Deutschland GmbH
Business Center
D-64306 Darmstadt
Germany
<‍hosting‍@‍telekom‍.‍de‍>
+49 800 5252033

The web service provider stores a session cookie in the web browser and records every visit of this web site with the following data in an access log on their server(s):


Copyright © 1995–2025 • Stefan Kanthak • <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>