// https://github.com/microsoft/Windows-classic-samples/blob/main/Samples/DataDedupBackupRestore/cpp/DedupBackupRestore.cpp
// https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-win32_stream_id
// https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_file_full_ea_information?redirectedfrom=MSDN

#include <windows.h>
#include <winternl.h>
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
	if (argc < 2) {
		fprintf(stderr, "get_ea <file name>");
		return 1;
	}

	HANDLE h = CreateFile(argv[1],
			GENERIC_EXECUTE|GENERIC_READ|GENERIC_WRITE,
			FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
			FILE_ATTRIBUTE_ARCHIVE, NULL);
	if (!h) {
		fprintf(stderr, "Error openingfile '%s'\n", argv[1]);
		return 1;
	}

	BYTE buffer[32768];
	DWORD read = 0;
	void *ctx = NULL;
	if (!BackupRead(h, buffer, sizeof(buffer), &read, FALSE, TRUE, &ctx)) {
		fprintf(stderr, "Error reading backup data\n");
		return 1;
	}

	BYTE *p = buffer;
	while (p < buffer + read) {
		WIN32_STREAM_ID *wsi = (WIN32_STREAM_ID*)p;

		// move past the part of the structure that is not counted by
		// the Size member, cStreamName and the data is
		p += FIELD_OFFSET(WIN32_STREAM_ID, cStreamName);

		if (wsi->dwStreamId != BACKUP_EA_DATA) {
			p += wsi->Size.QuadPart;
			continue;
		}

		// "streams" which are not alternate data streams do not have a
		// name and dwStreamNameSize will be zero but let's be strict
		// about it
		p += wsi->dwStreamNameSize;

		FILE_FULL_EA_INFORMATION *ffeai = (FILE_FULL_EA_INFORMATION *)p;
		while ((BYTE *)ffeai < p + wsi->Size.QuadPart) {
			fwrite(ffeai->EaName, ffeai->EaNameLength, 1, stdout);
			fwrite("=", 1, 1, stdout);

			BYTE *p2 = (BYTE *)ffeai +
				FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName)
				+ ffeai->EaNameLength + 1;

			fwrite(p2, ffeai->EaValueLength, 1, stdout);
			fwrite("\n", 1, 1, stdout);

			ffeai = (FILE_FULL_EA_INFORMATION *)(p2 + ffeai->EaValueLength);
		}

		break;
	}

	return 0;
}
