From: Grigory Vasilyev h0tc0d3@gmail.com
--- dlls/ntdll/unix/system.c | 73 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index f47925018b8..bf6f2815021 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -30,6 +30,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <errno.h> @@ -3682,9 +3683,77 @@ NTSTATUS WINAPI NtQuerySystemEnvironmentValue( UNICODE_STRING *name, WCHAR *buff NTSTATUS WINAPI NtQuerySystemEnvironmentValueEx( UNICODE_STRING *name, GUID *vendor, void *buffer, ULONG *retlen, ULONG *attrib ) { - FIXME( "(%s, %s, %p, %p, %p), stub\n", debugstr_us(name), - debugstr_guid(vendor), buffer, retlen, attrib ); +#if defined(__linux__) || defined(__gnu_linux__) + int fd, rc; + size_t bytes, pos = 0; + ssize_t ssz; + char filename[256]; + char *cname; + struct stat stat_info = {0}; + + if(!name || !vendor || !attrib) + { + return ERROR_INVALID_PARAMETER; + } + + cname = (char *) malloc(name->Length); + ntdll_wcstoumbs(name->Buffer, name->Length, cname, name->Length, FALSE); + + snprintf(filename, sizeof(filename), + "/sys/firmware/efi/efivars/%s-%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", cname, + (unsigned long)vendor->Data1, vendor->Data2, vendor->Data3, vendor->Data4[0], vendor->Data4[1], + vendor->Data4[2], vendor->Data4[3], vendor->Data4[4], vendor->Data4[5], + vendor->Data4[6], vendor->Data4[7]); + + fd = open(filename, O_RDONLY | O_NONBLOCK); + if (fd < 0) + goto done; + + rc = fstat(fd, &stat_info); + if (rc < 0 || stat_info.st_size == 0) + goto done; + +try_read_attributes: + ssz = read(fd, attrib, 4); + if (ssz < 0) + { + if (errno == EAGAIN || errno == EINTR) + goto try_read_attributes; + goto done; + } + + if(buffer && retlen) + { + if (stat_info.st_size - 4 < *retlen) + bytes = stat_info.st_size - 4; + else + bytes = *retlen; + while (pos < bytes) + { + ssz = read(fd, (char *) buffer + pos, bytes - pos); + if (ssz < 0) + { + if (errno == EAGAIN || errno == EINTR) + continue; + goto done; + } + pos += ssz; + } + *retlen = ssz & 0xFFFFFFFF; + } + + close(fd); + return STATUS_SUCCESS; + +done: + if (fd >= 0) + close(fd); + return STATUS_UNSUCCESSFUL; +#else + FIXME("(%s, %s, %p, %p, %p), stub\n", debugstr_us(name), debugstr_guid(vendor), buffer, retlen, + attrib); return STATUS_NOT_IMPLEMENTED; +#endif }