diff --git a/daemon/open.c b/daemon/open.c index 2f7b515..361c6ee 100644 --- a/daemon/open.c +++ b/daemon/open.c @@ -328,6 +328,23 @@ int marshall_open(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall) status = safe_write(&buffer, length, &args->mode, sizeof(args->mode)); if (status) goto out; status = safe_write(&buffer, length, &args->changeattr, sizeof(args->changeattr)); + if (status) goto out; + if (upcall->last_error == ERROR_REPARSE) { + /* convert args->path to wchar */ + WCHAR wpath[NFS41_MAX_PATH_LEN]; + unsigned short len = (unsigned short)MultiByteToWideChar( + CP_UTF8, 0, args->path.path, args->path.len, wpath, NFS41_MAX_PATH_LEN); + if (len == 0) { + status = ERROR_BUFFER_OVERFLOW; + goto out; + } + wpath[len++] = L'\0'; + len *= sizeof(WCHAR); + dprintf(2, "ERROR_REPARSE -> '%S' [%u]\n", wpath, len); + status = safe_write(&buffer, length, &len, sizeof(len)); + if (status) goto out; + status = safe_write(&buffer, length, wpath, len); + } dprintf(2, "NFS41_OPEN: passing open_state=0x%p mode %o changeattr 0x%x\n", args->state, args->mode, args->changeattr); out: diff --git a/sys/nfs41_driver.c b/sys/nfs41_driver.c index 60e272b..bb0812a 100644 --- a/sys/nfs41_driver.c +++ b/sys/nfs41_driver.c @@ -152,6 +152,7 @@ typedef struct _updowncall_entry { HANDLE session; HANDLE open_state; PUNICODE_STRING filename; + UNICODE_STRING symlink; ULONG access_mask; ULONG access_mode; ULONG attrs; @@ -1344,8 +1345,16 @@ nfs41_downcall ( buf += sizeof(HANDLE); RtlCopyMemory(&cur->u.Open.mode, buf, sizeof(DWORD)); buf += sizeof(DWORD); - RtlCopyMemory(&cur->u.Open.changeattr, buf, sizeof(ULONG)); - DbgP("[open] open_state 0x%x mode %o changeattr 0x%x\n", + RtlCopyMemory(&cur->u.Open.changeattr, buf, sizeof(LONGLONG)); + buf += sizeof(LONGLONG); + if (tmp->errno == ERROR_REPARSE) { + RtlCopyMemory(&cur->u.Open.symlink.MaximumLength, buf, sizeof(USHORT)); + buf += sizeof(USHORT); + cur->u.Open.symlink.Length = cur->u.Open.symlink.MaximumLength - sizeof(WCHAR); + cur->u.Open.symlink.Buffer = (PWCH)buf; + DbgP("[open] ERROR_REPARSE -> '%wZ'\n", &cur->u.Open.symlink); + } + DbgP("[open] open_state 0x%x mode %o changeattr 0x%x\n", cur->u.Open.open_state, cur->u.Open.mode, cur->u.Open.changeattr); break; case NFS41_DIR_QUERY: @@ -2457,6 +2466,7 @@ static NTSTATUS map_open_errors(DWORD status, int len) case ERROR_NETWORK_ACCESS_DENIED: return STATUS_NETWORK_ACCESS_DENIED; case ERROR_PATH_NOT_FOUND: return STATUS_OBJECT_PATH_NOT_FOUND; case ERROR_SHARING_VIOLATION: return STATUS_SHARING_VIOLATION; + case ERROR_REPARSE: return STATUS_REPARSE; default: DbgP("[ERROR] nfs41_Create: upcall returned %d returning " "STATUS_INSUFFICIENT_RESOURCES\n", status);