2011-08-12 13:20:12 -04:00
|
|
|
/* Copyright (c) 2010, 2011
|
2010-10-11 14:59:26 -04:00
|
|
|
* The Regents of the University of Michigan
|
|
|
|
|
* All Rights Reserved
|
2011-08-12 13:20:12 -04:00
|
|
|
*
|
|
|
|
|
* Olga Kornievskaia <aglo@umich.edu>
|
|
|
|
|
* Casey Bodley <cbodley@umich.edu>
|
2010-10-11 14:59:26 -04:00
|
|
|
*
|
|
|
|
|
* Permission is granted to use, copy and redistribute this software
|
|
|
|
|
* for noncommercial education and research purposes, so long as no
|
|
|
|
|
* fee is charged, and so long as the name of the University of Michigan
|
|
|
|
|
* is not used in any advertising or publicity pertaining to the use
|
|
|
|
|
* or distribution of this software without specific, written prior
|
|
|
|
|
* authorization. Permission to modify or otherwise create derivative
|
|
|
|
|
* works of this software is not granted.
|
|
|
|
|
*
|
|
|
|
|
* This software is provided as is, without representation or warranty
|
|
|
|
|
* of any kind either express or implied, including without limitation
|
|
|
|
|
* the implied warranties of merchantability, fitness for a particular
|
|
|
|
|
* purpose, or noninfringement. The Regents of the University of
|
|
|
|
|
* Michigan shall not be liable for any damages, including special,
|
|
|
|
|
* indirect, incidental, or consequential damages, with respect to any
|
|
|
|
|
* claim arising out of or in connection with the use of the software,
|
|
|
|
|
* even if it has been or is hereafter advised of the possibility of
|
|
|
|
|
* such damages.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#define MINIRDR__NAME "Value is ignored, only fact of definition"
|
|
|
|
|
#include <rx.h>
|
|
|
|
|
#include <windef.h>
|
|
|
|
|
#include <winerror.h>
|
|
|
|
|
|
|
|
|
|
#include <Ntstrsafe.h>
|
|
|
|
|
|
|
|
|
|
#include "nfs41_driver.h"
|
|
|
|
|
#include "nfs41_np.h"
|
|
|
|
|
#include "nfs41_debug.h"
|
|
|
|
|
|
2011-12-06 17:19:46 -05:00
|
|
|
#define USE_MOUNT_SEC_CONTEXT
|
2012-02-13 16:08:21 -05:00
|
|
|
|
|
|
|
|
/* debugging printout defines */
|
|
|
|
|
//#define DEBUG_OPEN
|
2010-10-11 14:59:26 -04:00
|
|
|
//#define DEBUG_CLOSE
|
2012-02-13 16:08:21 -05:00
|
|
|
//#define DEBUG_CACHE
|
|
|
|
|
//#define DEBUG_READ
|
|
|
|
|
//#define DEBUG_WRITE
|
|
|
|
|
//#define DEBUG_DIR_QUERY
|
|
|
|
|
//#define DEBUG_FILE_QUERY
|
|
|
|
|
//#define DEBUG_FILE_SET
|
|
|
|
|
//#define DEBUG_ACL_QUERY
|
|
|
|
|
//#define DEBUG_ACL_SET
|
|
|
|
|
//#define DEBUG_EA_QUERY
|
|
|
|
|
//#define DEBUG_EA_SET
|
|
|
|
|
//#define DEBUG_LOCK
|
|
|
|
|
|
2011-09-06 18:01:17 -04:00
|
|
|
//#define ENABLE_TIMINGS
|
|
|
|
|
//#define ENABLE_INDV_TIMINGS
|
|
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
typedef struct __nfs41_timings {
|
|
|
|
|
LONG tops, sops;
|
|
|
|
|
LONGLONG ticks, size;
|
|
|
|
|
} nfs41_timings;
|
|
|
|
|
|
|
|
|
|
nfs41_timings lookup, readdir, open, close, getattr, setattr, getacl, setacl, volume,
|
2011-09-22 14:56:11 -04:00
|
|
|
read, write, lock, unlock, setexattr, getexattr;
|
2011-09-06 18:01:17 -04:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
DRIVER_INITIALIZE DriverEntry;
|
|
|
|
|
DRIVER_UNLOAD nfs41_driver_unload;
|
|
|
|
|
DRIVER_DISPATCH ( nfs41_FsdDispatch );
|
|
|
|
|
|
|
|
|
|
struct _MINIRDR_DISPATCH nfs41_ops;
|
|
|
|
|
PRDBSS_DEVICE_OBJECT nfs41_dev;
|
|
|
|
|
|
|
|
|
|
#define FCB_BASIC_INFO_CACHED 0x0001
|
|
|
|
|
#define FCB_STANDARD_INFO_CACHED 0x0010
|
|
|
|
|
|
|
|
|
|
#define DISABLE_CACHING 0
|
|
|
|
|
#define ENABLE_READ_CACHING 1
|
|
|
|
|
#define ENABLE_WRITE_CACHING 2
|
|
|
|
|
#define ENABLE_READWRITE_CACHING 3
|
|
|
|
|
|
|
|
|
|
#define NFS41_MM_POOLTAG ('nfs4')
|
|
|
|
|
|
|
|
|
|
KEVENT upcallEvent;
|
2012-02-08 18:24:19 -05:00
|
|
|
FAST_MUTEX upcallLock, downcallLock, srvopenLock;
|
2010-10-11 14:59:26 -04:00
|
|
|
FAST_MUTEX xidLock;
|
|
|
|
|
FAST_MUTEX openOwnerLock;
|
|
|
|
|
|
2011-12-21 17:19:38 -05:00
|
|
|
LONGLONG xid = 0;
|
2011-12-21 17:42:04 -05:00
|
|
|
LONG open_owner_id = 1;
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
#define DECLARE_CONST_ANSI_STRING(_var, _string) \
|
|
|
|
|
const CHAR _var ## _buffer[] = _string; \
|
|
|
|
|
const ANSI_STRING _var = { sizeof(_string) - sizeof(CHAR), \
|
|
|
|
|
sizeof(_string), (PCH) _var ## _buffer }
|
|
|
|
|
|
|
|
|
|
DECLARE_CONST_ANSI_STRING(NfsV3Attributes, "NfsV3Attributes");
|
|
|
|
|
DECLARE_CONST_ANSI_STRING(NfsSymlinkTargetName, "NfsSymlinkTargetName");
|
|
|
|
|
DECLARE_CONST_ANSI_STRING(NfsActOnLink, "NfsActOnLink");
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
INLINE BOOL AnsiStrEq(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN const ANSI_STRING *lhs,
|
|
|
|
|
IN const CHAR *rhs,
|
|
|
|
|
IN const UCHAR rhs_len)
|
|
|
|
|
{
|
|
|
|
|
return lhs->Length == rhs_len &&
|
|
|
|
|
RtlCompareMemory(lhs->Buffer, rhs, rhs_len) == rhs_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef struct _nfs3_attrs {
|
|
|
|
|
DWORD type, mode, nlink, uid, gid, filler1;
|
|
|
|
|
LARGE_INTEGER size, used;
|
|
|
|
|
struct {
|
|
|
|
|
DWORD specdata1;
|
|
|
|
|
DWORD specdata2;
|
|
|
|
|
} rdev;
|
|
|
|
|
LONGLONG fsid, fileid;
|
2010-10-27 14:58:35 -04:00
|
|
|
LONGLONG atime, mtime, ctime;
|
2010-10-11 14:59:26 -04:00
|
|
|
} nfs3_attrs;
|
2010-10-27 14:58:35 -04:00
|
|
|
LARGE_INTEGER unix_time_diff; //needed to convert windows time to unix
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
enum ftype3 {
|
|
|
|
|
NF3REG = 1,
|
|
|
|
|
NF3DIR,
|
|
|
|
|
NF3BLK,
|
|
|
|
|
NF3CHR,
|
|
|
|
|
NF3LNK,
|
|
|
|
|
NF3SOCK,
|
|
|
|
|
NF3FIFO
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
typedef enum _nfs41_updowncall_state {
|
2011-12-21 15:53:17 -05:00
|
|
|
NFS41_WAITING_FOR_UPCALL,
|
|
|
|
|
NFS41_WAITING_FOR_DOWNCALL,
|
|
|
|
|
NFS41_DONE_PROCESSING,
|
|
|
|
|
NFS41_NOT_WAITING
|
2010-10-11 14:59:26 -04:00
|
|
|
} nfs41_updowncall_state;
|
|
|
|
|
|
|
|
|
|
typedef struct _updowncall_entry {
|
2010-11-05 20:08:55 -04:00
|
|
|
DWORD version;
|
2011-12-21 17:19:38 -05:00
|
|
|
LONGLONG xid;
|
2010-10-11 14:59:26 -04:00
|
|
|
DWORD opcode;
|
|
|
|
|
NTSTATUS status;
|
|
|
|
|
nfs41_updowncall_state state;
|
|
|
|
|
FAST_MUTEX lock;
|
|
|
|
|
LIST_ENTRY next;
|
|
|
|
|
KEVENT cond;
|
|
|
|
|
DWORD errno;
|
|
|
|
|
BOOLEAN async_op;
|
2010-10-12 10:02:20 -04:00
|
|
|
SECURITY_CLIENT_CONTEXT sec_ctx;
|
2011-01-07 14:49:41 -05:00
|
|
|
PSECURITY_CLIENT_CONTEXT psec_ctx;
|
2011-04-13 15:28:48 -04:00
|
|
|
HANDLE open_state;
|
|
|
|
|
HANDLE session;
|
2012-02-13 16:08:21 -05:00
|
|
|
PUNICODE_STRING filename;
|
2010-10-11 14:59:26 -04:00
|
|
|
union {
|
|
|
|
|
struct {
|
|
|
|
|
PUNICODE_STRING srv_name;
|
|
|
|
|
PUNICODE_STRING root;
|
2010-12-01 19:11:47 -05:00
|
|
|
DWORD sec_flavor;
|
2011-10-11 16:03:59 -04:00
|
|
|
DWORD rsize;
|
|
|
|
|
DWORD wsize;
|
2010-10-11 14:59:26 -04:00
|
|
|
} Mount;
|
2011-04-13 15:28:48 -04:00
|
|
|
struct {
|
2010-10-11 14:59:26 -04:00
|
|
|
PMDL MdlAddress;
|
|
|
|
|
PVOID buf;
|
|
|
|
|
LONGLONG offset;
|
|
|
|
|
ULONG len;
|
|
|
|
|
PRX_CONTEXT rxcontext;
|
2012-02-08 16:29:25 -05:00
|
|
|
ULONGLONG ChangeTime;
|
2010-10-11 14:59:26 -04:00
|
|
|
} ReadWrite;
|
|
|
|
|
struct {
|
|
|
|
|
LONGLONG offset;
|
|
|
|
|
LONGLONG length;
|
|
|
|
|
BOOLEAN exclusive;
|
|
|
|
|
BOOLEAN blocking;
|
|
|
|
|
} Lock;
|
|
|
|
|
struct {
|
|
|
|
|
ULONG count;
|
|
|
|
|
LOWIO_LOCK_LIST locks;
|
|
|
|
|
} Unlock;
|
|
|
|
|
struct {
|
|
|
|
|
FILE_BASIC_INFORMATION binfo;
|
|
|
|
|
FILE_STANDARD_INFORMATION sinfo;
|
|
|
|
|
PUNICODE_STRING filename;
|
2010-10-12 10:00:57 -04:00
|
|
|
UNICODE_STRING symlink;
|
2010-10-11 14:59:26 -04:00
|
|
|
ULONG access_mask;
|
|
|
|
|
ULONG access_mode;
|
|
|
|
|
ULONG attrs;
|
|
|
|
|
ULONG copts;
|
|
|
|
|
ULONG disp;
|
|
|
|
|
ULONG cattrs;
|
2011-12-21 17:42:04 -05:00
|
|
|
LONG open_owner_id;
|
2010-10-11 14:59:26 -04:00
|
|
|
DWORD mode;
|
2012-02-08 11:11:09 -05:00
|
|
|
ULONGLONG changeattr;
|
2012-01-19 19:46:03 -05:00
|
|
|
HANDLE srv_open;
|
2012-01-20 15:01:11 -05:00
|
|
|
DWORD deleg_type;
|
2010-09-29 13:11:27 -04:00
|
|
|
BOOLEAN symlink_embedded;
|
2010-10-11 14:59:26 -04:00
|
|
|
} Open;
|
|
|
|
|
struct {
|
|
|
|
|
PUNICODE_STRING filename;
|
2012-01-19 19:46:03 -05:00
|
|
|
HANDLE srv_open;
|
2010-10-11 14:59:26 -04:00
|
|
|
BOOLEAN remove;
|
|
|
|
|
BOOLEAN renamed;
|
|
|
|
|
} Close;
|
|
|
|
|
struct {
|
|
|
|
|
PUNICODE_STRING filter;
|
|
|
|
|
PVOID buf;
|
|
|
|
|
ULONG buf_len;
|
|
|
|
|
FILE_INFORMATION_CLASS InfoClass;
|
|
|
|
|
BOOLEAN restart_scan;
|
|
|
|
|
BOOLEAN return_single;
|
|
|
|
|
BOOLEAN initial_query;
|
2011-09-27 12:21:26 -04:00
|
|
|
PMDL mdl;
|
|
|
|
|
PVOID mdl_buf;
|
2012-02-06 14:23:47 -05:00
|
|
|
ULONGLONG ChangeTime;
|
2010-10-11 14:59:26 -04:00
|
|
|
} QueryFile;
|
|
|
|
|
struct {
|
|
|
|
|
PUNICODE_STRING filename;
|
|
|
|
|
PVOID buf;
|
|
|
|
|
ULONG buf_len;
|
|
|
|
|
FILE_INFORMATION_CLASS InfoClass;
|
2012-02-07 11:46:02 -05:00
|
|
|
ULONGLONG ChangeTime;
|
2010-10-11 14:59:26 -04:00
|
|
|
} SetFile;
|
|
|
|
|
struct {
|
2011-09-22 14:56:11 -04:00
|
|
|
PUNICODE_STRING filename;
|
|
|
|
|
PVOID buf;
|
|
|
|
|
ULONG buf_len;
|
2010-10-11 14:59:26 -04:00
|
|
|
DWORD mode;
|
2012-02-07 11:46:02 -05:00
|
|
|
ULONGLONG ChangeTime;
|
2010-10-11 14:59:26 -04:00
|
|
|
} SetEa;
|
2011-09-22 14:56:11 -04:00
|
|
|
struct {
|
|
|
|
|
PUNICODE_STRING filename;
|
|
|
|
|
PVOID buf;
|
|
|
|
|
ULONG buf_len;
|
|
|
|
|
PVOID EaList;
|
|
|
|
|
ULONG EaListLength;
|
|
|
|
|
ULONG EaIndex;
|
|
|
|
|
BOOLEAN ReturnSingleEntry;
|
|
|
|
|
BOOLEAN RestartScan;
|
|
|
|
|
} QueryEa;
|
2010-09-23 12:19:21 -04:00
|
|
|
struct {
|
|
|
|
|
PUNICODE_STRING filename;
|
|
|
|
|
PUNICODE_STRING target;
|
|
|
|
|
BOOLEAN set;
|
|
|
|
|
} Symlink;
|
2010-10-11 14:59:26 -04:00
|
|
|
struct {
|
2010-10-11 16:10:52 -04:00
|
|
|
FS_INFORMATION_CLASS query;
|
|
|
|
|
PVOID buf;
|
2011-12-22 11:59:45 -05:00
|
|
|
ULONG buf_len;
|
2010-10-11 14:59:26 -04:00
|
|
|
} Volume;
|
2011-04-12 15:56:20 -04:00
|
|
|
struct {
|
|
|
|
|
SECURITY_INFORMATION query;
|
|
|
|
|
PVOID buf;
|
2011-04-08 20:19:59 -04:00
|
|
|
DWORD buf_len;
|
2012-02-06 14:22:38 -05:00
|
|
|
ULONGLONG ChangeTime;
|
2011-04-08 20:19:59 -04:00
|
|
|
} Acl;
|
2010-10-11 14:59:26 -04:00
|
|
|
} u;
|
|
|
|
|
|
|
|
|
|
} nfs41_updowncall_entry;
|
|
|
|
|
|
|
|
|
|
typedef struct _updowncall_list {
|
|
|
|
|
LIST_ENTRY head;
|
|
|
|
|
} nfs41_updowncall_list;
|
|
|
|
|
nfs41_updowncall_list *upcall = NULL, *downcall = NULL;
|
|
|
|
|
|
2011-09-29 18:45:21 -04:00
|
|
|
typedef struct _nfs41_mount_entry {
|
|
|
|
|
LIST_ENTRY next;
|
|
|
|
|
LUID login_id;
|
|
|
|
|
HANDLE authsys_session;
|
|
|
|
|
HANDLE gss_session;
|
|
|
|
|
HANDLE gssi_session;
|
|
|
|
|
HANDLE gssp_session;
|
|
|
|
|
} nfs41_mount_entry;
|
|
|
|
|
|
|
|
|
|
typedef struct _nfs41_mount_list {
|
|
|
|
|
LIST_ENTRY head;
|
|
|
|
|
} nfs41_mount_list;
|
|
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
#define nfs41_AddEntry(lock,pList,pEntry) \
|
|
|
|
|
ExAcquireFastMutex(&lock); \
|
|
|
|
|
InsertTailList(&pList->head, &(pEntry)->next); \
|
|
|
|
|
ExReleaseFastMutex(&lock);
|
|
|
|
|
#define nfs41_RemoveFirst(lock,pList,pEntry) \
|
|
|
|
|
ExAcquireFastMutex(&lock); \
|
|
|
|
|
pEntry = (IsListEmpty(&pList->head) \
|
|
|
|
|
? NULL \
|
2011-12-21 15:53:17 -05:00
|
|
|
: RemoveHeadList(&pList->head)); \
|
2010-10-11 14:59:26 -04:00
|
|
|
ExReleaseFastMutex(&lock);
|
|
|
|
|
#define nfs41_RemoveEntry(lock,pList,pEntry) \
|
|
|
|
|
ExAcquireFastMutex(&lock); \
|
|
|
|
|
RemoveEntryList(&pEntry->next); \
|
|
|
|
|
ExReleaseFastMutex(&lock);
|
|
|
|
|
#define nfs41_IsListEmpty(lock,pList,flag) \
|
|
|
|
|
ExAcquireFastMutex(&lock); \
|
|
|
|
|
*flag = IsListEmpty(&pList->head); \
|
|
|
|
|
ExReleaseFastMutex(&lock);
|
|
|
|
|
#define nfs41_GetFirstEntry(lock,pList,pEntry) \
|
|
|
|
|
ExAcquireFastMutex(&lock); \
|
|
|
|
|
pEntry = (IsListEmpty(&pList->head) \
|
|
|
|
|
? NULL \
|
|
|
|
|
: (nfs41_updowncall_entry *) \
|
|
|
|
|
(CONTAINING_RECORD(pList->head.Flink, \
|
|
|
|
|
nfs41_updowncall_entry, \
|
|
|
|
|
next))); \
|
|
|
|
|
ExReleaseFastMutex(&lock);
|
2011-12-21 15:53:17 -05:00
|
|
|
#define nfs41_GetFirstMountEntry(lock,pList,pEntry) \
|
2011-09-29 18:45:21 -04:00
|
|
|
ExAcquireFastMutex(&lock); \
|
|
|
|
|
pEntry = (IsListEmpty(&pList->head) \
|
|
|
|
|
? NULL \
|
2011-12-21 15:53:17 -05:00
|
|
|
: (nfs41_mount_entry *) \
|
2011-09-29 18:45:21 -04:00
|
|
|
(CONTAINING_RECORD(pList->head.Flink, \
|
2011-12-21 15:53:17 -05:00
|
|
|
nfs41_mount_entry, \
|
2011-09-29 18:45:21 -04:00
|
|
|
next))); \
|
|
|
|
|
ExReleaseFastMutex(&lock);
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
/* In order to cooperate with other network providers,
|
|
|
|
|
* we only claim paths of the format '\\server\nfs4\path' */
|
|
|
|
|
DECLARE_CONST_UNICODE_STRING(NfsPrefix, L"\\nfs4");
|
2010-12-01 19:11:47 -05:00
|
|
|
DECLARE_CONST_UNICODE_STRING(AUTH_SYS_NAME, L"sys");
|
|
|
|
|
DECLARE_CONST_UNICODE_STRING(AUTHGSS_KRB5_NAME, L"krb5");
|
|
|
|
|
DECLARE_CONST_UNICODE_STRING(AUTHGSS_KRB5I_NAME, L"krb5i");
|
|
|
|
|
DECLARE_CONST_UNICODE_STRING(AUTHGSS_KRB5P_NAME, L"krb5p");
|
2012-02-13 16:08:21 -05:00
|
|
|
DECLARE_CONST_UNICODE_STRING(SLASH, L"\\");
|
|
|
|
|
DECLARE_CONST_UNICODE_STRING(EMPTY_STRING, L"");
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
#define SERVER_NAME_BUFFER_SIZE 1024
|
|
|
|
|
|
|
|
|
|
#define MOUNT_CONFIG_RW_SIZE_MIN 1024
|
2011-10-11 16:03:59 -04:00
|
|
|
#define MOUNT_CONFIG_RW_SIZE_DEFAULT 1048576
|
|
|
|
|
#define MOUNT_CONFIG_RW_SIZE_MAX 1048576
|
2010-12-01 19:11:47 -05:00
|
|
|
#define MAX_SEC_FLAVOR_LEN 12
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
typedef struct _NFS41_MOUNT_CONFIG {
|
|
|
|
|
DWORD ReadSize;
|
|
|
|
|
DWORD WriteSize;
|
|
|
|
|
BOOLEAN ReadOnly;
|
2011-12-07 18:10:09 -05:00
|
|
|
BOOLEAN write_thru;
|
2011-12-08 17:47:34 -05:00
|
|
|
BOOLEAN nocache;
|
2010-10-11 14:59:26 -04:00
|
|
|
WCHAR srv_buffer[SERVER_NAME_BUFFER_SIZE];
|
|
|
|
|
UNICODE_STRING SrvName;
|
|
|
|
|
WCHAR mntpt_buffer[MAX_PATH];
|
|
|
|
|
UNICODE_STRING MntPt;
|
2010-12-01 19:11:47 -05:00
|
|
|
WCHAR sec_flavor[MAX_SEC_FLAVOR_LEN];
|
|
|
|
|
UNICODE_STRING SecFlavor;
|
2010-10-11 14:59:26 -04:00
|
|
|
} NFS41_MOUNT_CONFIG, *PNFS41_MOUNT_CONFIG;
|
|
|
|
|
|
|
|
|
|
typedef struct _NFS41_NETROOT_EXTENSION {
|
|
|
|
|
NODE_TYPE_CODE NodeTypeCode;
|
|
|
|
|
NODE_BYTE_SIZE NodeByteSize;
|
2010-11-05 20:08:55 -04:00
|
|
|
DWORD nfs41d_version;
|
2011-09-29 18:45:21 -04:00
|
|
|
BOOLEAN mounts_init;
|
|
|
|
|
FAST_MUTEX mountLock;
|
|
|
|
|
nfs41_mount_list *mounts;
|
2010-10-11 14:59:26 -04:00
|
|
|
} NFS41_NETROOT_EXTENSION, *PNFS41_NETROOT_EXTENSION;
|
|
|
|
|
#define NFS41GetNetRootExtension(pNetRoot) \
|
2011-12-21 15:53:17 -05:00
|
|
|
(((pNetRoot) == NULL) ? NULL : \
|
|
|
|
|
(PNFS41_NETROOT_EXTENSION)((pNetRoot)->Context))
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2010-10-12 09:51:06 -04:00
|
|
|
/* FileSystemName as reported by FileFsAttributeInfo query */
|
|
|
|
|
#define FS_NAME L"NFS"
|
|
|
|
|
#define FS_NAME_LEN (sizeof(FS_NAME) - sizeof(WCHAR))
|
|
|
|
|
#define FS_ATTR_LEN (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + FS_NAME_LEN)
|
|
|
|
|
|
2011-12-22 14:50:53 -05:00
|
|
|
/* FileSystemName as reported by FileFsAttributeInfo query */
|
|
|
|
|
#define VOL_NAME L"PnfsVolume"
|
|
|
|
|
#define VOL_NAME_LEN (sizeof(VOL_NAME) - sizeof(WCHAR))
|
|
|
|
|
#define VOL_ATTR_LEN (sizeof(FILE_FS_VOLUME_INFORMATION) + VOL_NAME_LEN)
|
|
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
typedef struct _NFS41_V_NET_ROOT_EXTENSION {
|
|
|
|
|
NODE_TYPE_CODE NodeTypeCode;
|
|
|
|
|
NODE_BYTE_SIZE NodeByteSize;
|
|
|
|
|
HANDLE session;
|
2010-10-12 09:51:06 -04:00
|
|
|
BYTE FsAttrs[FS_ATTR_LEN];
|
|
|
|
|
LONG FsAttrsLen;
|
2011-10-04 10:57:06 -04:00
|
|
|
DWORD sec_flavor;
|
|
|
|
|
BOOLEAN read_only;
|
2011-12-07 18:10:09 -05:00
|
|
|
BOOLEAN write_thru;
|
2011-12-08 17:47:34 -05:00
|
|
|
BOOLEAN nocache;
|
2011-12-06 17:19:46 -05:00
|
|
|
#define STORE_MOUNT_SEC_CONTEXT
|
|
|
|
|
#ifdef STORE_MOUNT_SEC_CONTEXT
|
|
|
|
|
SECURITY_CLIENT_CONTEXT mount_sec_ctx;
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
} NFS41_V_NET_ROOT_EXTENSION, *PNFS41_V_NET_ROOT_EXTENSION;
|
|
|
|
|
#define NFS41GetVNetRootExtension(pVNetRoot) \
|
|
|
|
|
(((pVNetRoot) == NULL) ? NULL : \
|
|
|
|
|
(PNFS41_V_NET_ROOT_EXTENSION)((pVNetRoot)->Context))
|
|
|
|
|
|
|
|
|
|
typedef struct _NFS41_FCB {
|
|
|
|
|
NODE_TYPE_CODE NodeTypeCode;
|
|
|
|
|
NODE_BYTE_SIZE NodeByteSize;
|
|
|
|
|
ULONG Flags;
|
|
|
|
|
FILE_BASIC_INFORMATION BasicInfo;
|
|
|
|
|
FILE_STANDARD_INFORMATION StandardInfo;
|
|
|
|
|
BOOLEAN Renamed;
|
|
|
|
|
DWORD mode;
|
2012-02-08 11:11:09 -05:00
|
|
|
ULONGLONG changeattr;
|
2010-10-11 14:59:26 -04:00
|
|
|
} NFS41_FCB, *PNFS41_FCB;
|
|
|
|
|
#define NFS41GetFcbExtension(pFcb) \
|
|
|
|
|
(((pFcb) == NULL) ? NULL : (PNFS41_FCB)((pFcb)->Context))
|
|
|
|
|
|
|
|
|
|
typedef struct _NFS41_FOBX {
|
|
|
|
|
NODE_TYPE_CODE NodeTypeCode;
|
|
|
|
|
NODE_BYTE_SIZE NodeByteSize;
|
|
|
|
|
|
|
|
|
|
HANDLE nfs41_open_state;
|
2011-01-07 14:49:41 -05:00
|
|
|
SECURITY_CLIENT_CONTEXT sec_ctx;
|
2011-09-07 13:45:09 -04:00
|
|
|
PVOID acl;
|
2011-08-24 12:23:04 -04:00
|
|
|
DWORD acl_len;
|
|
|
|
|
LARGE_INTEGER time;
|
2012-02-08 18:24:19 -05:00
|
|
|
DWORD deleg_type;
|
2010-10-11 14:59:26 -04:00
|
|
|
} NFS41_FOBX, *PNFS41_FOBX;
|
2011-12-21 15:53:17 -05:00
|
|
|
#define NFS41GetFobxExtension(pFobx) \
|
2010-10-11 14:59:26 -04:00
|
|
|
(((pFobx) == NULL) ? NULL : (PNFS41_FOBX)((pFobx)->Context))
|
|
|
|
|
|
|
|
|
|
typedef struct _NFS41_SERVER_ENTRY {
|
|
|
|
|
PMRX_SRV_CALL pRdbssSrvCall;
|
|
|
|
|
WCHAR NameBuffer[SERVER_NAME_BUFFER_SIZE];
|
|
|
|
|
UNICODE_STRING Name; // the server name.
|
|
|
|
|
} NFS41_SERVER_ENTRY, *PNFS41_SERVER_ENTRY;
|
|
|
|
|
|
|
|
|
|
typedef struct _NFS41_DEVICE_EXTENSION {
|
|
|
|
|
NODE_TYPE_CODE NodeTypeCode;
|
|
|
|
|
NODE_BYTE_SIZE NodeByteSize;
|
|
|
|
|
PRDBSS_DEVICE_OBJECT DeviceObject;
|
|
|
|
|
ULONG ActiveNodes;
|
|
|
|
|
HANDLE SharedMemorySection;
|
2010-11-05 20:08:55 -04:00
|
|
|
DWORD nfs41d_version;
|
2011-12-22 14:50:53 -05:00
|
|
|
BYTE VolAttrs[VOL_ATTR_LEN];
|
|
|
|
|
DWORD VolAttrsLen;
|
2012-02-08 18:24:19 -05:00
|
|
|
HANDLE openlistHandle;
|
2010-10-11 14:59:26 -04:00
|
|
|
} NFS41_DEVICE_EXTENSION, *PNFS41_DEVICE_EXTENSION;
|
|
|
|
|
|
|
|
|
|
#define NFS41GetDeviceExtension(RxContext,pExt) \
|
|
|
|
|
PNFS41_DEVICE_EXTENSION pExt = (PNFS41_DEVICE_EXTENSION) \
|
|
|
|
|
((PBYTE)(RxContext->RxDeviceObject) + sizeof(RDBSS_DEVICE_OBJECT))
|
|
|
|
|
|
2012-02-08 18:24:19 -05:00
|
|
|
typedef struct _nfs41_srvopen_list_entry {
|
|
|
|
|
LIST_ENTRY next;
|
|
|
|
|
PMRX_SRV_OPEN srv_open;
|
|
|
|
|
PNFS41_FOBX nfs41_fobx;
|
|
|
|
|
ULONGLONG ChangeTime;
|
|
|
|
|
BOOLEAN skip;
|
|
|
|
|
} nfs41_srvopen_list_entry;
|
|
|
|
|
|
|
|
|
|
typedef struct _nfs41_srvopen_list {
|
|
|
|
|
LIST_ENTRY head;
|
|
|
|
|
} nfs41_srvopen_list;
|
|
|
|
|
nfs41_srvopen_list *openlist = NULL;
|
|
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
typedef enum _NULMRX_STORAGE_TYPE_CODES {
|
|
|
|
|
NTC_NFS41_DEVICE_EXTENSION = (NODE_TYPE_CODE)0xFC00,
|
|
|
|
|
} NFS41_STORAGE_TYPE_CODES;
|
|
|
|
|
#define RxDefineNode( node, type ) \
|
|
|
|
|
node->NodeTypeCode = NTC_##type; \
|
|
|
|
|
node->NodeByteSize = sizeof(type);
|
|
|
|
|
|
|
|
|
|
#define RDR_NULL_STATE 0
|
|
|
|
|
#define RDR_UNLOADED 1
|
|
|
|
|
#define RDR_UNLOADING 2
|
|
|
|
|
#define RDR_LOADING 3
|
|
|
|
|
#define RDR_LOADED 4
|
|
|
|
|
#define RDR_STOPPED 5
|
|
|
|
|
#define RDR_STOPPING 6
|
|
|
|
|
#define RDR_STARTING 7
|
|
|
|
|
#define RDR_STARTED 8
|
|
|
|
|
|
|
|
|
|
nfs41_init_driver_state nfs41_init_state = NFS41_INIT_DRIVER_STARTABLE;
|
|
|
|
|
nfs41_start_driver_state nfs41_start_state = NFS41_START_DRIVER_STARTABLE;
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS map_readwrite_errors(DWORD status);
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
void print_debug_header(
|
|
|
|
|
PRX_CONTEXT RxContext)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
|
|
|
|
|
PIO_STACK_LOCATION IrpSp = RxContext->CurrentIrpSp;
|
|
|
|
|
|
|
|
|
|
if (IrpSp) {
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("FileOject %p name %wZ\n", IrpSp->FileObject,
|
|
|
|
|
&IrpSp->FileObject->FileName);
|
2010-10-11 14:59:26 -04:00
|
|
|
print_file_object(0, IrpSp->FileObject);
|
2012-02-13 16:08:21 -05:00
|
|
|
print_irps_flags(0, RxContext->CurrentIrpSp);
|
2010-10-11 14:59:26 -04:00
|
|
|
} else
|
|
|
|
|
DbgP("Couldn't print FileObject IrpSp is NULL\n");
|
2011-04-14 20:14:21 -04:00
|
|
|
|
|
|
|
|
print_fo_all(1, RxContext);
|
|
|
|
|
if (RxContext->CurrentIrp)
|
2012-02-13 16:08:21 -05:00
|
|
|
print_irp_flags(0, RxContext->CurrentIrp);
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
|
2010-10-12 10:03:26 -04:00
|
|
|
/* convert strings from unicode -> ansi during marshalling to
|
|
|
|
|
* save space in the upcall buffers and avoid extra copies */
|
2011-12-21 15:53:17 -05:00
|
|
|
INLINE ULONG length_as_ansi(
|
2010-10-12 10:03:26 -04:00
|
|
|
PCUNICODE_STRING str)
|
|
|
|
|
{
|
|
|
|
|
return sizeof(str->MaximumLength) + RtlUnicodeStringToAnsiSize(str);
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS marshall_unicode_as_ansi(
|
|
|
|
|
IN OUT unsigned char **pos,
|
|
|
|
|
IN PCUNICODE_STRING str)
|
2010-10-12 10:03:26 -04:00
|
|
|
{
|
|
|
|
|
ANSI_STRING ansi;
|
|
|
|
|
NTSTATUS status;
|
|
|
|
|
|
|
|
|
|
/* convert the string directly into the upcall buffer */
|
|
|
|
|
ansi.Buffer = (PCHAR)*pos + sizeof(ansi.MaximumLength);
|
|
|
|
|
ansi.MaximumLength = (USHORT)RtlUnicodeStringToAnsiSize(str);
|
|
|
|
|
status = RtlUnicodeStringToAnsiString(&ansi, str, FALSE);
|
|
|
|
|
if (status)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
RtlCopyMemory(*pos, &ansi.MaximumLength, sizeof(ansi.MaximumLength));
|
|
|
|
|
*pos += sizeof(ansi.MaximumLength);
|
|
|
|
|
(*pos)[ansi.Length] = '\0';
|
|
|
|
|
*pos += ansi.MaximumLength;
|
|
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS marshal_nfs41_header(
|
|
|
|
|
nfs41_updowncall_entry *entry,
|
|
|
|
|
unsigned char *buf,
|
|
|
|
|
ULONG buf_len,
|
|
|
|
|
ULONG *len)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
ULONG header_len = 0;
|
|
|
|
|
unsigned char *tmp = buf;
|
|
|
|
|
|
2011-04-13 20:07:37 -04:00
|
|
|
header_len = sizeof(entry->version) + sizeof(entry->xid) +
|
|
|
|
|
sizeof(entry->opcode) + 2 * sizeof(HANDLE);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (header_len > buf_len) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
*len = header_len;
|
2010-11-05 20:08:55 -04:00
|
|
|
RtlCopyMemory(tmp, &entry->version, sizeof(entry->version));
|
2011-04-13 20:07:37 -04:00
|
|
|
tmp += sizeof(entry->version);
|
2010-10-11 14:59:26 -04:00
|
|
|
RtlCopyMemory(tmp, &entry->xid, sizeof(entry->xid));
|
2011-04-13 20:07:37 -04:00
|
|
|
tmp += sizeof(entry->xid);
|
2010-10-11 14:59:26 -04:00
|
|
|
RtlCopyMemory(tmp, &entry->opcode, sizeof(entry->opcode));
|
2011-04-13 20:07:37 -04:00
|
|
|
tmp += sizeof(entry->opcode);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->session, sizeof(HANDLE));
|
|
|
|
|
tmp += sizeof(HANDLE);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->open_state, sizeof(HANDLE));
|
|
|
|
|
tmp += sizeof(HANDLE);
|
2010-10-12 10:02:20 -04:00
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("[upcall header] xid=%lld opcode=%s filename=%wZ version=%d "
|
|
|
|
|
"session=0x%x open_state=0x%x\n", entry->xid,
|
|
|
|
|
opcode2string(entry->opcode), entry->filename,
|
|
|
|
|
entry->version, entry->session, entry->open_state);
|
2010-10-11 14:59:26 -04:00
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
const char* secflavorop2name(
|
|
|
|
|
DWORD sec_flavor)
|
2010-12-01 19:11:47 -05:00
|
|
|
{
|
|
|
|
|
switch(sec_flavor) {
|
|
|
|
|
case RPCSEC_AUTH_SYS: return "AUTH_SYS";
|
|
|
|
|
case RPCSEC_AUTHGSS_KRB5: return "AUTHGSS_KRB5";
|
|
|
|
|
case RPCSEC_AUTHGSS_KRB5I: return "AUTHGSS_KRB5I";
|
|
|
|
|
case RPCSEC_AUTHGSS_KRB5P: return "AUTHGSS_KRB5P";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return "UNKNOWN FLAVOR";
|
|
|
|
|
}
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS marshal_nfs41_mount(
|
|
|
|
|
nfs41_updowncall_entry *entry,
|
|
|
|
|
unsigned char *buf,
|
|
|
|
|
ULONG buf_len,
|
|
|
|
|
ULONG *len)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
ULONG header_len = 0;
|
|
|
|
|
unsigned char *tmp = buf;
|
|
|
|
|
|
|
|
|
|
status = marshal_nfs41_header(entry, tmp, buf_len, len);
|
|
|
|
|
if (status == STATUS_INSUFFICIENT_RESOURCES)
|
|
|
|
|
goto out;
|
|
|
|
|
else
|
|
|
|
|
tmp += *len;
|
2011-03-25 13:11:08 -04:00
|
|
|
/* 03/25/2011: Kernel crash to nfsd not running but mount upcall cued up */
|
|
|
|
|
if (!MmIsAddressValid(entry->u.Mount.srv_name) ||
|
|
|
|
|
!MmIsAddressValid(entry->u.Mount.root)) {
|
|
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2010-10-12 10:03:26 -04:00
|
|
|
header_len = *len + length_as_ansi(entry->u.Mount.srv_name) +
|
2011-10-11 16:03:59 -04:00
|
|
|
length_as_ansi(entry->u.Mount.root) + 3 * sizeof(DWORD);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (header_len > buf_len) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2010-10-12 10:03:26 -04:00
|
|
|
status = marshall_unicode_as_ansi(&tmp, entry->u.Mount.srv_name);
|
|
|
|
|
if (status) goto out;
|
|
|
|
|
status = marshall_unicode_as_ansi(&tmp, entry->u.Mount.root);
|
|
|
|
|
if (status) goto out;
|
2011-10-11 16:03:59 -04:00
|
|
|
RtlCopyMemory(tmp, &entry->u.Mount.sec_flavor, sizeof(DWORD));
|
|
|
|
|
tmp += sizeof(DWORD);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.Mount.rsize, sizeof(DWORD));
|
|
|
|
|
tmp += sizeof(DWORD);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.Mount.wsize, sizeof(DWORD));
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
*len = header_len;
|
|
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("marshal_nfs41_mount: server name=%wZ mount point=%wZ sec_flavor=%s "
|
2011-10-11 16:03:59 -04:00
|
|
|
"rsize=%d wsize=%d\n", entry->u.Mount.srv_name, entry->u.Mount.root,
|
|
|
|
|
secflavorop2name(entry->u.Mount.sec_flavor), entry->u.Mount.rsize,
|
|
|
|
|
entry->u.Mount.wsize);
|
2010-10-11 14:59:26 -04:00
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS marshal_nfs41_unmount(
|
|
|
|
|
nfs41_updowncall_entry *entry,
|
|
|
|
|
unsigned char *buf,
|
|
|
|
|
ULONG buf_len,
|
|
|
|
|
ULONG *len)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
2012-02-13 16:08:21 -05:00
|
|
|
return marshal_nfs41_header(entry, buf, buf_len, len);
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS marshal_nfs41_open(
|
|
|
|
|
nfs41_updowncall_entry *entry,
|
|
|
|
|
unsigned char *buf,
|
|
|
|
|
ULONG buf_len,
|
|
|
|
|
ULONG *len)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
ULONG header_len = 0;
|
|
|
|
|
unsigned char *tmp = buf;
|
|
|
|
|
|
|
|
|
|
status = marshal_nfs41_header(entry, tmp, buf_len, len);
|
|
|
|
|
if (status == STATUS_INSUFFICIENT_RESOURCES)
|
|
|
|
|
goto out;
|
|
|
|
|
else
|
|
|
|
|
tmp += *len;
|
2010-10-12 10:03:26 -04:00
|
|
|
header_len = *len + length_as_ansi(entry->u.Open.filename) +
|
2012-01-19 19:46:03 -05:00
|
|
|
5 * sizeof(ULONG) + sizeof(LONG) + sizeof(DWORD) + sizeof(HANDLE);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (header_len > buf_len) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2010-10-12 10:03:26 -04:00
|
|
|
status = marshall_unicode_as_ansi(&tmp, entry->u.Open.filename);
|
|
|
|
|
if (status) goto out;
|
2011-12-21 15:53:17 -05:00
|
|
|
RtlCopyMemory(tmp, &entry->u.Open.access_mask,
|
|
|
|
|
sizeof(entry->u.Open.access_mask));
|
2010-10-11 14:59:26 -04:00
|
|
|
tmp += sizeof(entry->u.Open.access_mask);
|
2011-12-21 15:53:17 -05:00
|
|
|
RtlCopyMemory(tmp, &entry->u.Open.access_mode,
|
|
|
|
|
sizeof(entry->u.Open.access_mode));
|
2010-10-11 14:59:26 -04:00
|
|
|
tmp += sizeof(entry->u.Open.access_mode);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.Open.attrs, sizeof(entry->u.Open.attrs));
|
|
|
|
|
tmp += sizeof(entry->u.Open.attrs);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.Open.copts, sizeof(entry->u.Open.copts));
|
|
|
|
|
tmp += sizeof(entry->u.Open.copts);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.Open.disp, sizeof(entry->u.Open.disp));
|
|
|
|
|
tmp += sizeof(entry->u.Open.disp);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.Open.open_owner_id,
|
|
|
|
|
sizeof(entry->u.Open.open_owner_id));
|
|
|
|
|
tmp += sizeof(entry->u.Open.open_owner_id);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.Open.mode, sizeof(DWORD));
|
2012-01-19 19:46:03 -05:00
|
|
|
tmp += sizeof(DWORD);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.Open.srv_open, sizeof(HANDLE));
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
*len = header_len;
|
|
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("marshal_nfs41_open: name=%wZ mask=0x%x access=0x%x attrs=0x%x "
|
|
|
|
|
"opts=0x%x dispo=0x%x open_owner_id=0x%x mode=%o srv_open=%p\n",
|
|
|
|
|
entry->u.Open.filename, entry->u.Open.access_mask,
|
|
|
|
|
entry->u.Open.access_mode, entry->u.Open.attrs, entry->u.Open.copts,
|
|
|
|
|
entry->u.Open.disp, entry->u.Open.open_owner_id, entry->u.Open.mode,
|
2012-01-19 19:46:03 -05:00
|
|
|
entry->u.Open.srv_open);
|
2010-10-11 14:59:26 -04:00
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS marshal_nfs41_rw(
|
|
|
|
|
nfs41_updowncall_entry *entry,
|
|
|
|
|
unsigned char *buf,
|
|
|
|
|
ULONG buf_len,
|
|
|
|
|
ULONG *len)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
ULONG header_len = 0;
|
|
|
|
|
unsigned char *tmp = buf;
|
|
|
|
|
|
|
|
|
|
status = marshal_nfs41_header(entry, tmp, buf_len, len);
|
|
|
|
|
if (status == STATUS_INSUFFICIENT_RESOURCES)
|
|
|
|
|
goto out;
|
|
|
|
|
else
|
|
|
|
|
tmp += *len;
|
|
|
|
|
header_len = *len + sizeof(entry->u.ReadWrite.len) +
|
2011-04-13 20:07:37 -04:00
|
|
|
sizeof(entry->u.ReadWrite.offset) + sizeof(HANDLE);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (header_len > buf_len) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.ReadWrite.len, sizeof(entry->u.ReadWrite.len));
|
|
|
|
|
tmp += sizeof(entry->u.ReadWrite.len);
|
2011-12-21 15:53:17 -05:00
|
|
|
RtlCopyMemory(tmp, &entry->u.ReadWrite.offset,
|
|
|
|
|
sizeof(entry->u.ReadWrite.offset));
|
2010-10-11 14:59:26 -04:00
|
|
|
tmp += sizeof(entry->u.ReadWrite.offset);
|
|
|
|
|
__try {
|
2011-10-06 12:32:50 -04:00
|
|
|
entry->u.ReadWrite.MdlAddress->MdlFlags |= MDL_MAPPING_CAN_FAIL;
|
2010-10-11 14:59:26 -04:00
|
|
|
entry->u.ReadWrite.buf =
|
|
|
|
|
MmMapLockedPagesSpecifyCache(entry->u.ReadWrite.MdlAddress,
|
2010-12-17 13:31:23 -05:00
|
|
|
UserMode, MmNonCached, NULL, TRUE, NormalPagePriority);
|
|
|
|
|
if (entry->u.ReadWrite.buf == NULL) {
|
|
|
|
|
print_error("MmMapLockedPagesSpecifyCache failed to map pages\n");
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2010-10-11 14:59:26 -04:00
|
|
|
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
|
NTSTATUS code;
|
|
|
|
|
code = GetExceptionCode();
|
2010-12-17 13:31:23 -05:00
|
|
|
print_error("Call to MmMapLocked failed due to exception 0x%x\n", code);
|
2010-10-11 14:59:26 -04:00
|
|
|
status = STATUS_ACCESS_DENIED;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.ReadWrite.buf, sizeof(HANDLE));
|
|
|
|
|
|
|
|
|
|
*len = header_len;
|
|
|
|
|
|
2011-04-14 20:14:21 -04:00
|
|
|
DbgP("marshal_nfs41_rw: len=%u offset=%lu MdlAddress=%p Userspace=%p\n",
|
|
|
|
|
entry->u.ReadWrite.len, entry->u.ReadWrite.offset,
|
|
|
|
|
entry->u.ReadWrite.MdlAddress, entry->u.ReadWrite.buf);
|
2010-10-11 14:59:26 -04:00
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS marshal_nfs41_lock(
|
|
|
|
|
nfs41_updowncall_entry *entry,
|
|
|
|
|
unsigned char *buf,
|
|
|
|
|
ULONG buf_len,
|
|
|
|
|
ULONG *len)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
ULONG header_len = 0;
|
|
|
|
|
unsigned char *tmp = buf;
|
|
|
|
|
|
|
|
|
|
status = marshal_nfs41_header(entry, tmp, buf_len, len);
|
|
|
|
|
if (status == STATUS_INSUFFICIENT_RESOURCES)
|
|
|
|
|
goto out;
|
|
|
|
|
else
|
|
|
|
|
tmp += *len;
|
|
|
|
|
|
2011-04-13 20:07:37 -04:00
|
|
|
header_len = *len + 2 * sizeof(LONGLONG) + 2 * sizeof(BOOLEAN);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (header_len > buf_len) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.Lock.offset, sizeof(LONGLONG));
|
|
|
|
|
tmp += sizeof(LONGLONG);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.Lock.length, sizeof(LONGLONG));
|
|
|
|
|
tmp += sizeof(LONGLONG);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.Lock.exclusive, sizeof(BOOLEAN));
|
|
|
|
|
tmp += sizeof(BOOLEAN);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.Lock.blocking, sizeof(BOOLEAN));
|
|
|
|
|
tmp += sizeof(BOOLEAN);
|
|
|
|
|
|
|
|
|
|
*len = header_len;
|
|
|
|
|
|
2011-04-14 20:14:21 -04:00
|
|
|
DbgP("marshal_nfs41_lock: offset=%llx length=%llx exclusive=%u "
|
|
|
|
|
"blocking=%u\n", entry->u.Lock.offset, entry->u.Lock.length,
|
|
|
|
|
entry->u.Lock.exclusive, entry->u.Lock.blocking);
|
2010-10-11 14:59:26 -04:00
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS marshal_nfs41_unlock(
|
|
|
|
|
nfs41_updowncall_entry *entry,
|
|
|
|
|
unsigned char *buf,
|
|
|
|
|
ULONG buf_len,
|
|
|
|
|
ULONG *len)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
2010-10-11 14:59:26 -04:00
|
|
|
ULONG header_len = 0;
|
|
|
|
|
unsigned char *tmp = buf;
|
|
|
|
|
PLOWIO_LOCK_LIST lock;
|
|
|
|
|
|
|
|
|
|
status = marshal_nfs41_header(entry, tmp, buf_len, len);
|
|
|
|
|
if (status == STATUS_INSUFFICIENT_RESOURCES)
|
|
|
|
|
goto out;
|
|
|
|
|
else
|
|
|
|
|
tmp += *len;
|
|
|
|
|
|
2011-04-13 20:07:37 -04:00
|
|
|
header_len = *len + sizeof(ULONG) +
|
2010-10-11 14:59:26 -04:00
|
|
|
entry->u.Unlock.count * 2 * sizeof(LONGLONG);
|
|
|
|
|
if (header_len > buf_len) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.Unlock.count, sizeof(ULONG));
|
|
|
|
|
tmp += sizeof(ULONG);
|
|
|
|
|
|
|
|
|
|
lock = &entry->u.Unlock.locks;
|
|
|
|
|
while (lock) {
|
|
|
|
|
RtlCopyMemory(tmp, &lock->ByteOffset, sizeof(LONGLONG));
|
|
|
|
|
tmp += sizeof(LONGLONG);
|
|
|
|
|
RtlCopyMemory(tmp, &lock->Length, sizeof(LONGLONG));
|
|
|
|
|
tmp += sizeof(LONGLONG);
|
|
|
|
|
lock = lock->Next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*len = header_len;
|
|
|
|
|
|
2011-04-14 20:14:21 -04:00
|
|
|
DbgP("marshal_nfs41_unlock: count=%u\n", entry->u.Unlock.count);
|
2010-10-11 14:59:26 -04:00
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS marshal_nfs41_close(
|
|
|
|
|
nfs41_updowncall_entry *entry,
|
|
|
|
|
unsigned char *buf,
|
|
|
|
|
ULONG buf_len,
|
|
|
|
|
ULONG *len)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
ULONG header_len = 0;
|
|
|
|
|
unsigned char *tmp = buf;
|
|
|
|
|
|
|
|
|
|
status = marshal_nfs41_header(entry, tmp, buf_len, len);
|
|
|
|
|
if (status == STATUS_INSUFFICIENT_RESOURCES)
|
|
|
|
|
goto out;
|
|
|
|
|
else
|
|
|
|
|
tmp += *len;
|
|
|
|
|
|
|
|
|
|
|
2012-01-19 19:46:03 -05:00
|
|
|
header_len = *len + sizeof(BOOLEAN) + sizeof(HANDLE);
|
2010-10-12 10:03:26 -04:00
|
|
|
if (entry->u.Close.remove)
|
|
|
|
|
header_len += length_as_ansi(entry->u.Close.filename) +
|
2010-10-11 14:59:26 -04:00
|
|
|
sizeof(BOOLEAN);
|
|
|
|
|
|
|
|
|
|
if (header_len > buf_len) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.Close.remove, sizeof(BOOLEAN));
|
2012-01-19 19:46:03 -05:00
|
|
|
tmp += sizeof(BOOLEAN);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.Close.srv_open, sizeof(HANDLE));
|
2010-10-11 14:59:26 -04:00
|
|
|
if (entry->u.Close.remove) {
|
2012-01-19 19:46:03 -05:00
|
|
|
tmp += sizeof(HANDLE);
|
2010-10-12 10:03:26 -04:00
|
|
|
status = marshall_unicode_as_ansi(&tmp, entry->u.Close.filename);
|
|
|
|
|
if (status) goto out;
|
2010-10-11 14:59:26 -04:00
|
|
|
RtlCopyMemory(tmp, &entry->u.Close.renamed, sizeof(BOOLEAN));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*len = header_len;
|
|
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("marshal_nfs41_close: name=%wZ remove=%d srv_open=%p renamed=%d\n",
|
|
|
|
|
entry->u.Close.filename->Length?entry->u.Close.filename:&SLASH,
|
|
|
|
|
entry->u.Close.remove, entry->u.Close.srv_open, entry->u.Close.renamed);
|
2010-10-11 14:59:26 -04:00
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS marshal_nfs41_dirquery(
|
|
|
|
|
nfs41_updowncall_entry *entry,
|
|
|
|
|
unsigned char *buf,
|
|
|
|
|
ULONG buf_len,
|
|
|
|
|
ULONG *len)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
ULONG header_len = 0;
|
|
|
|
|
unsigned char *tmp = buf;
|
|
|
|
|
|
|
|
|
|
status = marshal_nfs41_header(entry, tmp, buf_len, len);
|
|
|
|
|
if (status == STATUS_INSUFFICIENT_RESOURCES)
|
|
|
|
|
goto out;
|
|
|
|
|
else
|
|
|
|
|
tmp += *len;
|
|
|
|
|
|
2011-09-27 12:21:26 -04:00
|
|
|
header_len = *len + 2 * sizeof(ULONG) + sizeof(HANDLE) +
|
2011-04-13 20:07:37 -04:00
|
|
|
length_as_ansi(entry->u.QueryFile.filter) + 3 * sizeof(BOOLEAN);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (header_len > buf_len) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.QueryFile.InfoClass, sizeof(ULONG));
|
|
|
|
|
tmp += sizeof(ULONG);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.QueryFile.buf_len, sizeof(ULONG));
|
|
|
|
|
tmp += sizeof(ULONG);
|
2010-10-12 10:03:26 -04:00
|
|
|
status = marshall_unicode_as_ansi(&tmp, entry->u.QueryFile.filter);
|
|
|
|
|
if (status) goto out;
|
2010-10-11 14:59:26 -04:00
|
|
|
RtlCopyMemory(tmp, &entry->u.QueryFile.initial_query, sizeof(BOOLEAN));
|
|
|
|
|
tmp += sizeof(BOOLEAN);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.QueryFile.restart_scan, sizeof(BOOLEAN));
|
|
|
|
|
tmp += sizeof(BOOLEAN);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.QueryFile.return_single, sizeof(BOOLEAN));
|
2011-09-27 12:21:26 -04:00
|
|
|
tmp += sizeof(BOOLEAN);
|
|
|
|
|
__try {
|
|
|
|
|
entry->u.QueryFile.mdl_buf =
|
|
|
|
|
MmMapLockedPagesSpecifyCache(entry->u.QueryFile.mdl,
|
|
|
|
|
UserMode, MmNonCached, NULL, TRUE, NormalPagePriority);
|
|
|
|
|
if (entry->u.QueryFile.mdl_buf == NULL) {
|
|
|
|
|
print_error("MmMapLockedPagesSpecifyCache failed to map pages\n");
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
|
NTSTATUS code;
|
|
|
|
|
code = GetExceptionCode();
|
|
|
|
|
print_error("Call to MmMapLocked failed due to exception 0x%x\n", code);
|
|
|
|
|
status = STATUS_ACCESS_DENIED;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.QueryFile.mdl_buf, sizeof(HANDLE));
|
2010-10-11 14:59:26 -04:00
|
|
|
*len = header_len;
|
|
|
|
|
|
2011-09-27 12:21:26 -04:00
|
|
|
DbgP("marshal_nfs41_dirquery: filter='%wZ'class=%d len=%d "
|
2011-04-14 20:14:21 -04:00
|
|
|
"1st\\restart\\single=%d\\%d\\%d\n", entry->u.QueryFile.filter,
|
2011-09-27 12:21:26 -04:00
|
|
|
entry->u.QueryFile.InfoClass, entry->u.QueryFile.buf_len,
|
|
|
|
|
entry->u.QueryFile.initial_query, entry->u.QueryFile.restart_scan,
|
|
|
|
|
entry->u.QueryFile.return_single);
|
2010-10-11 14:59:26 -04:00
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS marshal_nfs41_filequery(
|
|
|
|
|
nfs41_updowncall_entry *entry,
|
|
|
|
|
unsigned char *buf,
|
|
|
|
|
ULONG buf_len,
|
|
|
|
|
ULONG *len)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
ULONG header_len = 0;
|
|
|
|
|
unsigned char *tmp = buf;
|
|
|
|
|
|
|
|
|
|
status = marshal_nfs41_header(entry, tmp, buf_len, len);
|
|
|
|
|
if (status == STATUS_INSUFFICIENT_RESOURCES)
|
|
|
|
|
goto out;
|
|
|
|
|
else
|
|
|
|
|
tmp += *len;
|
2011-04-13 20:07:37 -04:00
|
|
|
header_len = *len + 2 * sizeof(ULONG);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (header_len > buf_len) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.QueryFile.InfoClass, sizeof(ULONG));
|
|
|
|
|
tmp += sizeof(ULONG);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.QueryFile.buf_len, sizeof(ULONG));
|
|
|
|
|
tmp += sizeof(ULONG);
|
2011-04-13 15:28:48 -04:00
|
|
|
RtlCopyMemory(tmp, &entry->session, sizeof(HANDLE));
|
2010-10-11 14:59:26 -04:00
|
|
|
tmp += sizeof(HANDLE);
|
2011-04-13 15:28:48 -04:00
|
|
|
RtlCopyMemory(tmp, &entry->open_state, sizeof(HANDLE));
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
*len = header_len;
|
|
|
|
|
|
2011-04-14 20:14:21 -04:00
|
|
|
DbgP("marshal_nfs41_filequery: class=%d\n", entry->u.QueryFile.InfoClass);
|
2010-10-11 14:59:26 -04:00
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS marshal_nfs41_fileset(
|
|
|
|
|
nfs41_updowncall_entry *entry,
|
|
|
|
|
unsigned char *buf,
|
|
|
|
|
ULONG buf_len,
|
|
|
|
|
ULONG *len)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
ULONG header_len = 0;
|
|
|
|
|
unsigned char *tmp = buf;
|
|
|
|
|
|
|
|
|
|
status = marshal_nfs41_header(entry, tmp, buf_len, len);
|
|
|
|
|
if (status == STATUS_INSUFFICIENT_RESOURCES)
|
|
|
|
|
goto out;
|
|
|
|
|
else
|
|
|
|
|
tmp += *len;
|
2010-10-12 10:03:26 -04:00
|
|
|
header_len = *len + length_as_ansi(entry->u.SetFile.filename) +
|
2012-02-09 10:36:07 -05:00
|
|
|
2 * sizeof(ULONG) + entry->u.SetFile.buf_len;
|
2010-10-11 14:59:26 -04:00
|
|
|
if (header_len > buf_len) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2010-10-12 10:03:26 -04:00
|
|
|
status = marshall_unicode_as_ansi(&tmp, entry->u.SetFile.filename);
|
|
|
|
|
if (status) goto out;
|
2010-10-11 14:59:26 -04:00
|
|
|
RtlCopyMemory(tmp, &entry->u.SetFile.InfoClass, sizeof(ULONG));
|
|
|
|
|
tmp += sizeof(ULONG);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.SetFile.buf_len, sizeof(ULONG));
|
|
|
|
|
tmp += sizeof(ULONG);
|
|
|
|
|
RtlCopyMemory(tmp, entry->u.SetFile.buf, entry->u.SetFile.buf_len);
|
|
|
|
|
tmp += entry->u.SetFile.buf_len;
|
|
|
|
|
|
|
|
|
|
*len = header_len;
|
|
|
|
|
|
2011-06-27 12:01:24 -04:00
|
|
|
DbgP("marshal_nfs41_fileset: filename='%wZ' class=%d\n",
|
|
|
|
|
entry->u.SetFile.filename, entry->u.SetFile.InfoClass);
|
|
|
|
|
print_hexbuf(0, (unsigned char *)"setfile buffer", entry->u.SetFile.buf,
|
2010-10-11 14:59:26 -04:00
|
|
|
entry->u.SetFile.buf_len);
|
|
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS marshal_nfs41_easet(
|
|
|
|
|
nfs41_updowncall_entry *entry,
|
|
|
|
|
unsigned char *buf,
|
|
|
|
|
ULONG buf_len,
|
|
|
|
|
ULONG *len)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
ULONG header_len = 0;
|
|
|
|
|
unsigned char *tmp = buf;
|
|
|
|
|
|
|
|
|
|
status = marshal_nfs41_header(entry, tmp, buf_len, len);
|
|
|
|
|
if (status == STATUS_INSUFFICIENT_RESOURCES)
|
|
|
|
|
goto out;
|
|
|
|
|
else
|
|
|
|
|
tmp += *len;
|
2011-09-22 14:56:11 -04:00
|
|
|
header_len = *len + length_as_ansi(entry->u.SetEa.filename) +
|
|
|
|
|
sizeof(ULONG) + entry->u.SetEa.buf_len + sizeof(DWORD);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (header_len > buf_len) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-22 14:56:11 -04:00
|
|
|
status = marshall_unicode_as_ansi(&tmp, entry->u.SetEa.filename);
|
|
|
|
|
if (status) goto out;
|
2010-10-11 14:59:26 -04:00
|
|
|
RtlCopyMemory(tmp, &entry->u.SetEa.mode, sizeof(DWORD));
|
2011-09-22 14:56:11 -04:00
|
|
|
tmp += sizeof(DWORD);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.SetEa.buf_len, sizeof(ULONG));
|
|
|
|
|
tmp += sizeof(ULONG);
|
|
|
|
|
RtlCopyMemory(tmp, entry->u.SetEa.buf, entry->u.SetEa.buf_len);
|
|
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
*len = header_len;
|
|
|
|
|
|
2011-09-22 14:56:11 -04:00
|
|
|
DbgP("marshal_nfs41_easet: filename=%wZ, buflen=%d mode=0x%x\n",
|
|
|
|
|
entry->u.SetEa.filename, entry->u.SetEa.buf_len, entry->u.SetEa.mode);
|
|
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS marshal_nfs41_eaget(
|
|
|
|
|
nfs41_updowncall_entry *entry,
|
2011-09-22 14:56:11 -04:00
|
|
|
unsigned char *buf,
|
|
|
|
|
ULONG buf_len,
|
|
|
|
|
ULONG *len)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
ULONG header_len = 0;
|
|
|
|
|
unsigned char *tmp = buf;
|
|
|
|
|
|
|
|
|
|
status = marshal_nfs41_header(entry, tmp, buf_len, len);
|
|
|
|
|
if (status == STATUS_INSUFFICIENT_RESOURCES)
|
|
|
|
|
goto out;
|
|
|
|
|
else
|
|
|
|
|
tmp += *len;
|
|
|
|
|
header_len = *len + length_as_ansi(entry->u.QueryEa.filename) +
|
|
|
|
|
2 * sizeof(ULONG) + entry->u.QueryEa.EaListLength + 2 * sizeof(BOOLEAN);
|
|
|
|
|
|
|
|
|
|
if (header_len > buf_len) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
status = marshall_unicode_as_ansi(&tmp, entry->u.QueryEa.filename);
|
|
|
|
|
if (status) goto out;
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.QueryEa.EaIndex, sizeof(ULONG));
|
|
|
|
|
tmp += sizeof(ULONG);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.QueryEa.RestartScan, sizeof(BOOLEAN));
|
|
|
|
|
tmp += sizeof(BOOLEAN);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.QueryEa.ReturnSingleEntry, sizeof(BOOLEAN));
|
|
|
|
|
tmp += sizeof(BOOLEAN);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.QueryEa.EaListLength, sizeof(ULONG));
|
|
|
|
|
tmp += sizeof(ULONG);
|
|
|
|
|
RtlCopyMemory(tmp, entry->u.QueryEa.EaList, entry->u.QueryEa.EaListLength);
|
|
|
|
|
|
|
|
|
|
*len = header_len;
|
|
|
|
|
|
|
|
|
|
DbgP("marshal_nfs41_eaget: filename=%wZ, index=%d list_len=%d "
|
|
|
|
|
"rescan=%d single=%d\n", entry->u.QueryEa.filename,
|
|
|
|
|
entry->u.QueryEa.EaIndex, entry->u.QueryEa.EaListLength,
|
|
|
|
|
entry->u.QueryEa.RestartScan, entry->u.QueryEa.ReturnSingleEntry);
|
2010-10-11 14:59:26 -04:00
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS marshal_nfs41_symlink(
|
|
|
|
|
nfs41_updowncall_entry *entry,
|
2010-09-23 12:19:21 -04:00
|
|
|
unsigned char *buf,
|
|
|
|
|
ULONG buf_len,
|
|
|
|
|
ULONG *len)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
ULONG header_len = 0;
|
|
|
|
|
unsigned char *tmp = buf;
|
|
|
|
|
|
|
|
|
|
status = marshal_nfs41_header(entry, tmp, buf_len, len);
|
|
|
|
|
if (status == STATUS_INSUFFICIENT_RESOURCES)
|
|
|
|
|
goto out;
|
|
|
|
|
else
|
|
|
|
|
tmp += *len;
|
2011-04-13 20:07:37 -04:00
|
|
|
header_len = *len + sizeof(BOOLEAN) +
|
2010-09-23 12:19:21 -04:00
|
|
|
length_as_ansi(entry->u.Symlink.filename);
|
|
|
|
|
if (entry->u.Symlink.set)
|
|
|
|
|
header_len += length_as_ansi(entry->u.Symlink.target);
|
|
|
|
|
if (header_len > buf_len) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
marshall_unicode_as_ansi(&tmp, entry->u.Symlink.filename);
|
|
|
|
|
RtlCopyMemory(tmp, &entry->u.Symlink.set, sizeof(BOOLEAN));
|
|
|
|
|
tmp += sizeof(BOOLEAN);
|
|
|
|
|
if (entry->u.Symlink.set)
|
|
|
|
|
marshall_unicode_as_ansi(&tmp, entry->u.Symlink.target);
|
|
|
|
|
|
|
|
|
|
*len = header_len;
|
|
|
|
|
|
2011-04-14 20:14:21 -04:00
|
|
|
DbgP("marshal_nfs41_symlink: name %wZ symlink target %wZ\n",
|
|
|
|
|
entry->u.Symlink.filename,
|
|
|
|
|
entry->u.Symlink.set?entry->u.Symlink.target : NULL);
|
2010-09-23 12:19:21 -04:00
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS marshal_nfs41_volume(
|
|
|
|
|
nfs41_updowncall_entry *entry,
|
2010-10-11 14:59:26 -04:00
|
|
|
unsigned char *buf,
|
|
|
|
|
ULONG buf_len,
|
|
|
|
|
ULONG *len)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
ULONG header_len = 0;
|
|
|
|
|
unsigned char *tmp = buf;
|
|
|
|
|
|
|
|
|
|
status = marshal_nfs41_header(entry, tmp, buf_len, len);
|
|
|
|
|
if (status == STATUS_INSUFFICIENT_RESOURCES)
|
|
|
|
|
goto out;
|
|
|
|
|
else
|
|
|
|
|
tmp += *len;
|
2011-04-13 20:07:37 -04:00
|
|
|
header_len = *len + sizeof(FS_INFORMATION_CLASS);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (header_len > buf_len) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-11 16:10:52 -04:00
|
|
|
RtlCopyMemory(tmp, &entry->u.Volume.query, sizeof(FS_INFORMATION_CLASS));
|
2010-10-11 14:59:26 -04:00
|
|
|
*len = header_len;
|
|
|
|
|
|
2011-04-14 20:14:21 -04:00
|
|
|
DbgP("marshal_nfs41_volume: class=%d\n", entry->u.Volume.query);
|
2010-10-11 14:59:26 -04:00
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS marshal_nfs41_getacl(
|
|
|
|
|
nfs41_updowncall_entry *entry,
|
2011-03-15 16:31:52 -04:00
|
|
|
unsigned char *buf,
|
|
|
|
|
ULONG buf_len,
|
|
|
|
|
ULONG *len)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
ULONG header_len = 0;
|
|
|
|
|
unsigned char *tmp = buf;
|
|
|
|
|
|
|
|
|
|
status = marshal_nfs41_header(entry, tmp, buf_len, len);
|
|
|
|
|
if (status == STATUS_INSUFFICIENT_RESOURCES)
|
|
|
|
|
goto out;
|
|
|
|
|
else
|
|
|
|
|
tmp += *len;
|
2011-04-13 20:07:37 -04:00
|
|
|
header_len = *len + sizeof(SECURITY_INFORMATION);
|
2011-03-15 16:31:52 -04:00
|
|
|
if (header_len > buf_len) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-08 20:19:59 -04:00
|
|
|
RtlCopyMemory(tmp, &entry->u.Acl.query, sizeof(SECURITY_INFORMATION));
|
2011-03-15 16:31:52 -04:00
|
|
|
*len = header_len;
|
|
|
|
|
|
2011-04-14 20:14:21 -04:00
|
|
|
DbgP("marshal_nfs41_getacl: class=0x%x\n", entry->u.Acl.query);
|
2011-03-15 16:31:52 -04:00
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS marshal_nfs41_setacl(
|
|
|
|
|
nfs41_updowncall_entry *entry,
|
2011-04-12 15:56:20 -04:00
|
|
|
unsigned char *buf,
|
|
|
|
|
ULONG buf_len,
|
|
|
|
|
ULONG *len)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
ULONG header_len = 0;
|
|
|
|
|
unsigned char *tmp = buf;
|
|
|
|
|
|
|
|
|
|
status = marshal_nfs41_header(entry, tmp, buf_len, len);
|
|
|
|
|
if (status == STATUS_INSUFFICIENT_RESOURCES)
|
|
|
|
|
goto out;
|
|
|
|
|
else
|
|
|
|
|
tmp += *len;
|
2011-04-13 20:07:37 -04:00
|
|
|
header_len = *len + sizeof(SECURITY_INFORMATION) +
|
2011-04-08 20:19:59 -04:00
|
|
|
sizeof(ULONG) + entry->u.Acl.buf_len;
|
2011-04-12 15:56:20 -04:00
|
|
|
if (header_len > buf_len) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-08 20:19:59 -04:00
|
|
|
RtlCopyMemory(tmp, &entry->u.Acl.query, sizeof(SECURITY_INFORMATION));
|
2011-04-12 15:56:20 -04:00
|
|
|
tmp += sizeof(SECURITY_INFORMATION);
|
2011-04-08 20:19:59 -04:00
|
|
|
RtlCopyMemory(tmp, &entry->u.Acl.buf_len, sizeof(DWORD));
|
|
|
|
|
tmp += sizeof(DWORD);
|
|
|
|
|
RtlCopyMemory(tmp, entry->u.Acl.buf, entry->u.Acl.buf_len);
|
2011-04-12 15:56:20 -04:00
|
|
|
*len = header_len;
|
|
|
|
|
|
2011-04-14 20:14:21 -04:00
|
|
|
DbgP("marshal_nfs41_setacl: class=0x%x sec_desc_len=%d\n",
|
|
|
|
|
entry->u.Acl.query, entry->u.Acl.buf_len);
|
2011-04-12 15:56:20 -04:00
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS marshal_nfs41_shutdown(
|
|
|
|
|
nfs41_updowncall_entry *entry,
|
|
|
|
|
unsigned char *buf,
|
|
|
|
|
ULONG buf_len,
|
|
|
|
|
ULONG *len)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
2012-02-13 16:08:21 -05:00
|
|
|
return marshal_nfs41_header(entry, buf, buf_len, len);
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_invalidate_cache (
|
|
|
|
|
IN PRX_CONTEXT RxContext)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
2012-01-19 19:46:03 -05:00
|
|
|
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
|
|
|
|
|
unsigned char *buf = LowIoContext->ParamsFor.IoCtl.pInputBuffer;
|
|
|
|
|
ULONG flag = DISABLE_CACHING;
|
|
|
|
|
PMRX_SRV_OPEN srv_open;
|
|
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
2012-01-19 19:46:03 -05:00
|
|
|
RtlCopyMemory(&srv_open, buf, sizeof(HANDLE));
|
|
|
|
|
|
|
|
|
|
DbgP("nfs41_invalidate_cache: received srv_open=%p\n", srv_open);
|
|
|
|
|
if (MmIsAddressValid(srv_open))
|
|
|
|
|
RxChangeBufferingState((PSRV_OPEN)srv_open, ULongToPtr(flag), 1);
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS handle_upcall(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN PRX_CONTEXT RxContext,
|
|
|
|
|
IN nfs41_updowncall_entry *entry,
|
2011-12-21 15:53:17 -05:00
|
|
|
OUT ULONG *len)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
|
|
|
|
|
ULONG cbOut = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
|
|
|
|
|
unsigned char *pbOut = LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
|
|
|
|
|
|
2011-01-07 14:49:41 -05:00
|
|
|
status = SeImpersonateClientEx(entry->psec_ctx, NULL);
|
2011-12-22 12:06:44 -05:00
|
|
|
if (status != STATUS_SUCCESS) {
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("SeImpersonateClientEx failed %x\n", status);
|
2011-12-22 12:06:44 -05:00
|
|
|
goto out;
|
|
|
|
|
}
|
2010-10-12 10:02:20 -04:00
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
switch(entry->opcode) {
|
|
|
|
|
case NFS41_SHUTDOWN:
|
|
|
|
|
status = marshal_nfs41_shutdown(entry, pbOut, cbOut, len);
|
|
|
|
|
KeSetEvent(&entry->cond, 0, FALSE);
|
|
|
|
|
break;
|
|
|
|
|
case NFS41_MOUNT:
|
|
|
|
|
status = marshal_nfs41_mount(entry, pbOut, cbOut, len);
|
|
|
|
|
break;
|
|
|
|
|
case NFS41_UNMOUNT:
|
|
|
|
|
status = marshal_nfs41_unmount(entry, pbOut, cbOut, len);
|
|
|
|
|
break;
|
|
|
|
|
case NFS41_OPEN:
|
|
|
|
|
status = marshal_nfs41_open(entry, pbOut, cbOut, len);
|
|
|
|
|
break;
|
|
|
|
|
case NFS41_READ:
|
|
|
|
|
status = marshal_nfs41_rw(entry, pbOut, cbOut, len);
|
|
|
|
|
break;
|
|
|
|
|
case NFS41_WRITE:
|
|
|
|
|
status = marshal_nfs41_rw(entry, pbOut, cbOut, len);
|
|
|
|
|
break;
|
|
|
|
|
case NFS41_LOCK:
|
|
|
|
|
status = marshal_nfs41_lock(entry, pbOut, cbOut, len);
|
|
|
|
|
break;
|
|
|
|
|
case NFS41_UNLOCK:
|
|
|
|
|
status = marshal_nfs41_unlock(entry, pbOut, cbOut, len);
|
|
|
|
|
break;
|
|
|
|
|
case NFS41_CLOSE:
|
|
|
|
|
status = marshal_nfs41_close(entry, pbOut, cbOut, len);
|
|
|
|
|
break;
|
|
|
|
|
case NFS41_DIR_QUERY:
|
|
|
|
|
status = marshal_nfs41_dirquery(entry, pbOut, cbOut, len);
|
|
|
|
|
break;
|
|
|
|
|
case NFS41_FILE_QUERY:
|
|
|
|
|
status = marshal_nfs41_filequery(entry, pbOut, cbOut, len);
|
|
|
|
|
break;
|
|
|
|
|
case NFS41_FILE_SET:
|
|
|
|
|
status = marshal_nfs41_fileset(entry, pbOut, cbOut, len);
|
|
|
|
|
break;
|
|
|
|
|
case NFS41_EA_SET:
|
|
|
|
|
status = marshal_nfs41_easet(entry, pbOut, cbOut, len);
|
|
|
|
|
break;
|
2011-09-22 14:56:11 -04:00
|
|
|
case NFS41_EA_GET:
|
|
|
|
|
status = marshal_nfs41_eaget(entry, pbOut, cbOut, len);
|
|
|
|
|
break;
|
2010-09-23 12:19:21 -04:00
|
|
|
case NFS41_SYMLINK:
|
|
|
|
|
status = marshal_nfs41_symlink(entry, pbOut, cbOut, len);
|
|
|
|
|
break;
|
2010-10-11 14:59:26 -04:00
|
|
|
case NFS41_VOLUME_QUERY:
|
|
|
|
|
status = marshal_nfs41_volume(entry, pbOut, cbOut, len);
|
|
|
|
|
break;
|
2011-03-15 16:31:52 -04:00
|
|
|
case NFS41_ACL_QUERY:
|
|
|
|
|
status = marshal_nfs41_getacl(entry, pbOut, cbOut, len);
|
|
|
|
|
break;
|
2011-04-12 15:56:20 -04:00
|
|
|
case NFS41_ACL_SET:
|
|
|
|
|
status = marshal_nfs41_setacl(entry, pbOut, cbOut, len);
|
|
|
|
|
break;
|
2010-10-11 14:59:26 -04:00
|
|
|
default:
|
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("Unknown nfs41 ops %d\n", entry->opcode);
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status == STATUS_SUCCESS)
|
|
|
|
|
print_hexbuf(0, (unsigned char *)"upcall buffer", pbOut, *len);
|
|
|
|
|
|
2011-12-22 12:06:44 -05:00
|
|
|
out:
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
2010-10-12 09:55:32 -04:00
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
NTSTATUS nfs41_UpcallCreate(
|
|
|
|
|
IN DWORD opcode,
|
2011-01-07 14:49:41 -05:00
|
|
|
IN PSECURITY_CLIENT_CONTEXT clnt_sec_ctx,
|
2011-04-13 15:28:48 -04:00
|
|
|
IN HANDLE session,
|
|
|
|
|
IN HANDLE open_state,
|
|
|
|
|
IN DWORD version,
|
2012-02-13 16:08:21 -05:00
|
|
|
IN PUNICODE_STRING filename,
|
2010-10-11 14:59:26 -04:00
|
|
|
OUT nfs41_updowncall_entry **entry_out)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
nfs41_updowncall_entry *entry;
|
2010-10-12 09:55:32 -04:00
|
|
|
SECURITY_SUBJECT_CONTEXT sec_ctx;
|
2010-10-12 10:02:20 -04:00
|
|
|
SECURITY_QUALITY_OF_SERVICE sec_qos;
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
entry = RxAllocatePoolWithTag(NonPagedPool, sizeof(nfs41_updowncall_entry),
|
|
|
|
|
NFS41_MM_POOLTAG);
|
|
|
|
|
if (entry == NULL) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RtlZeroMemory(entry, sizeof(nfs41_updowncall_entry));
|
2011-12-21 17:19:38 -05:00
|
|
|
entry->xid = InterlockedIncrement64(&xid);
|
2010-10-11 14:59:26 -04:00
|
|
|
entry->opcode = opcode;
|
|
|
|
|
entry->state = NFS41_WAITING_FOR_UPCALL;
|
2011-04-13 15:28:48 -04:00
|
|
|
entry->session = session;
|
|
|
|
|
entry->open_state = open_state;
|
|
|
|
|
entry->version = version;
|
2012-02-13 16:08:21 -05:00
|
|
|
if (filename && filename->Length) entry->filename = filename;
|
|
|
|
|
else if (filename && !filename->Length) entry->filename = (PUNICODE_STRING)&SLASH;
|
|
|
|
|
else entry->filename = (PUNICODE_STRING)&EMPTY_STRING;
|
2011-12-21 15:53:17 -05:00
|
|
|
/*XXX KeInitializeEvent will bugcheck under verifier if allocated
|
|
|
|
|
* from PagedPool? */
|
2010-10-11 14:59:26 -04:00
|
|
|
KeInitializeEvent(&entry->cond, SynchronizationEvent, FALSE);
|
|
|
|
|
ExInitializeFastMutex(&entry->lock);
|
2010-10-12 09:55:32 -04:00
|
|
|
|
2011-01-07 14:49:41 -05:00
|
|
|
if (clnt_sec_ctx == NULL) {
|
|
|
|
|
SeCaptureSubjectContext(&sec_ctx);
|
|
|
|
|
sec_qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
|
|
|
|
|
sec_qos.ImpersonationLevel = SecurityImpersonation;
|
|
|
|
|
sec_qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
|
|
|
|
|
sec_qos.EffectiveOnly = 0;
|
2011-12-21 15:53:17 -05:00
|
|
|
status = SeCreateClientSecurityFromSubjectContext(&sec_ctx, &sec_qos,
|
|
|
|
|
1, &entry->sec_ctx);
|
2011-01-07 14:49:41 -05:00
|
|
|
if (status != STATUS_SUCCESS) {
|
2011-12-21 15:53:17 -05:00
|
|
|
print_error("nfs41_UpcallCreate: "
|
|
|
|
|
"SeCreateClientSecurityFromSubjectContext failed with %x\n",
|
|
|
|
|
status);
|
2011-01-07 14:49:41 -05:00
|
|
|
RxFreePool(entry);
|
2011-06-08 12:54:31 -04:00
|
|
|
} else
|
|
|
|
|
entry->psec_ctx = &entry->sec_ctx;
|
2011-01-07 14:49:41 -05:00
|
|
|
SeReleaseSubjectContext(&sec_ctx);
|
|
|
|
|
} else
|
|
|
|
|
entry->psec_ctx = clnt_sec_ctx;
|
2010-10-12 09:55:32 -04:00
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
*entry_out = entry;
|
|
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_UpcallWaitForReply(
|
|
|
|
|
IN nfs41_updowncall_entry *entry)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
|
|
nfs41_AddEntry(upcallLock, upcall, entry);
|
|
|
|
|
KeSetEvent(&upcallEvent, 0, FALSE);
|
|
|
|
|
if (!entry->async_op) {
|
2011-12-21 15:53:17 -05:00
|
|
|
/* 02/03/2011 AGLO: it is not clear what the "right" waiting design
|
|
|
|
|
* should be. Having non-interruptable waiting seems to be the right
|
|
|
|
|
* approach. However, when things go wrong, the only wait to proceed
|
|
|
|
|
* is a reboot (since "waits" are not interruptable we can't stop a
|
|
|
|
|
* hung task. Having interruptable wait causes issues with security
|
|
|
|
|
* context. For now, I'm making CLOSE non-interruptable but keeping
|
|
|
|
|
* the rest interruptable so that we don't have to reboot all the time
|
2011-02-03 11:46:51 -05:00
|
|
|
*/
|
2011-02-15 15:04:57 -05:00
|
|
|
/* 02/15/2011 cbodley: added NFS41_UNLOCK for the same reason. locking
|
|
|
|
|
* tests were triggering an interrupted unlock, which led to a bugcheck
|
|
|
|
|
* in CloseSrvOpen() */
|
2011-02-03 11:46:51 -05:00
|
|
|
#define MAKE_WAITONCLOSE_NONITERRUPTABLE
|
|
|
|
|
#ifdef MAKE_WAITONCLOSE_NONITERRUPTABLE
|
2011-02-15 15:04:57 -05:00
|
|
|
if (entry->opcode == NFS41_CLOSE || entry->opcode == NFS41_UNLOCK)
|
2011-02-03 11:46:51 -05:00
|
|
|
status = KeWaitForSingleObject(&entry->cond, Executive,
|
|
|
|
|
KernelMode, FALSE, NULL);
|
|
|
|
|
else
|
|
|
|
|
status = KeWaitForSingleObject(&entry->cond, Executive,
|
|
|
|
|
UserMode, TRUE, NULL);
|
|
|
|
|
#else
|
|
|
|
|
|
2011-01-07 14:51:50 -05:00
|
|
|
status = KeWaitForSingleObject(&entry->cond, Executive, KernelMode, FALSE, NULL);
|
2011-02-03 11:46:51 -05:00
|
|
|
#endif
|
2012-02-13 16:08:21 -05:00
|
|
|
print_wait_status(0, "[downcall]", status, opcode2string(entry->opcode),
|
2010-10-11 14:59:26 -04:00
|
|
|
entry, entry->xid);
|
2011-12-21 15:53:17 -05:00
|
|
|
} else
|
2010-10-11 14:59:26 -04:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
switch(status) {
|
2011-12-21 15:53:17 -05:00
|
|
|
case STATUS_SUCCESS: break;
|
2010-10-11 14:59:26 -04:00
|
|
|
case STATUS_USER_APC:
|
|
|
|
|
case STATUS_ALERTED:
|
|
|
|
|
default:
|
|
|
|
|
ExAcquireFastMutex(&entry->lock);
|
|
|
|
|
if (entry->state == NFS41_DONE_PROCESSING) {
|
|
|
|
|
ExReleaseFastMutex(&entry->lock);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2011-12-21 17:19:38 -05:00
|
|
|
DbgP("[upcall] abandoning %s entry=%p xid=%lld\n",
|
2010-10-11 14:59:26 -04:00
|
|
|
opcode2string(entry->opcode), entry, entry->xid);
|
|
|
|
|
entry->state = NFS41_NOT_WAITING;
|
|
|
|
|
ExReleaseFastMutex(&entry->lock);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
nfs41_RemoveEntry(downcallLock, downcall, entry);
|
|
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_upcall(
|
|
|
|
|
IN PRX_CONTEXT RxContext)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
2010-10-11 14:59:26 -04:00
|
|
|
nfs41_updowncall_entry *entry = NULL;
|
|
|
|
|
ULONG len = 0;
|
|
|
|
|
PLIST_ENTRY pEntry;
|
|
|
|
|
|
|
|
|
|
process_upcall:
|
|
|
|
|
nfs41_RemoveFirst(upcallLock, upcall, pEntry);
|
|
|
|
|
if (pEntry) {
|
|
|
|
|
entry = (nfs41_updowncall_entry *)CONTAINING_RECORD(pEntry,
|
|
|
|
|
nfs41_updowncall_entry, next);
|
|
|
|
|
ExAcquireFastMutex(&entry->lock);
|
2010-10-20 17:04:26 -04:00
|
|
|
nfs41_AddEntry(downcallLock, downcall, entry);
|
|
|
|
|
status = handle_upcall(RxContext, entry, &len);
|
|
|
|
|
if (status == STATUS_SUCCESS &&
|
|
|
|
|
entry->state == NFS41_WAITING_FOR_UPCALL)
|
|
|
|
|
entry->state = NFS41_WAITING_FOR_DOWNCALL;
|
2010-10-11 14:59:26 -04:00
|
|
|
ExReleaseFastMutex(&entry->lock);
|
2011-12-22 12:06:44 -05:00
|
|
|
if (status) {
|
2010-10-11 14:59:26 -04:00
|
|
|
entry->status = status;
|
|
|
|
|
KeSetEvent(&entry->cond, 0, FALSE);
|
|
|
|
|
RxContext->InformationToReturn = 0;
|
|
|
|
|
} else
|
|
|
|
|
RxContext->InformationToReturn = len;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
status = KeWaitForSingleObject(&upcallEvent, Executive, UserMode, TRUE,
|
|
|
|
|
(PLARGE_INTEGER) NULL);
|
2012-02-13 16:08:21 -05:00
|
|
|
print_wait_status(0, "[upcall]", status, NULL, NULL, 0);
|
2010-10-11 14:59:26 -04:00
|
|
|
switch (status) {
|
2011-12-21 15:53:17 -05:00
|
|
|
case STATUS_SUCCESS: goto process_upcall;
|
2010-10-11 14:59:26 -04:00
|
|
|
case STATUS_USER_APC:
|
|
|
|
|
case STATUS_ALERTED:
|
2011-12-21 15:53:17 -05:00
|
|
|
default: goto out;
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-22 11:59:45 -05:00
|
|
|
void unmarshal_nfs41_header(
|
|
|
|
|
nfs41_updowncall_entry *tmp,
|
|
|
|
|
unsigned char **buf)
|
|
|
|
|
{
|
|
|
|
|
RtlZeroMemory(tmp, sizeof(nfs41_updowncall_entry));
|
|
|
|
|
|
|
|
|
|
RtlCopyMemory(&tmp->xid, *buf, sizeof(tmp->xid));
|
|
|
|
|
*buf += sizeof(tmp->xid);
|
|
|
|
|
RtlCopyMemory(&tmp->opcode, *buf, sizeof(tmp->opcode));
|
|
|
|
|
*buf += sizeof(tmp->opcode);
|
|
|
|
|
RtlCopyMemory(&tmp->status, *buf, sizeof(tmp->status));
|
|
|
|
|
*buf += sizeof(tmp->status);
|
|
|
|
|
RtlCopyMemory(&tmp->errno, *buf, sizeof(tmp->errno));
|
|
|
|
|
*buf += sizeof(tmp->errno);
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("[downcall header] xid=%lld opcode=%s status=%d errno=%d\n", tmp->xid,
|
|
|
|
|
opcode2string(tmp->opcode), tmp->status, tmp->errno);
|
2011-12-22 11:59:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void unmarshal_nfs41_mount(
|
|
|
|
|
nfs41_updowncall_entry *cur,
|
|
|
|
|
unsigned char **buf)
|
|
|
|
|
{
|
|
|
|
|
RtlCopyMemory(&cur->session, *buf, sizeof(HANDLE));
|
|
|
|
|
*buf += sizeof(HANDLE);
|
|
|
|
|
RtlCopyMemory(&cur->version, *buf, sizeof(DWORD));
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("unmarshal_nfs41_mount: session pointer 0x%x version %d\n", cur->session,
|
2011-12-22 11:59:45 -05:00
|
|
|
cur->version);
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-07 11:46:02 -05:00
|
|
|
VOID unmarshal_nfs41_setattr(
|
|
|
|
|
nfs41_updowncall_entry *cur,
|
|
|
|
|
PULONGLONG dest_buf,
|
|
|
|
|
unsigned char **buf)
|
|
|
|
|
{
|
|
|
|
|
RtlCopyMemory(dest_buf, *buf, sizeof(ULONGLONG));
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("unmarshal_nfs41_setattr: returned ChangeTime %llu\n", *dest_buf);
|
2012-02-07 11:46:02 -05:00
|
|
|
}
|
|
|
|
|
|
2011-12-22 11:59:45 -05:00
|
|
|
NTSTATUS unmarshal_nfs41_rw(
|
|
|
|
|
nfs41_updowncall_entry *cur,
|
|
|
|
|
unsigned char **buf)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
|
|
RtlCopyMemory(&cur->u.ReadWrite.len, *buf, sizeof(cur->u.ReadWrite.len));
|
2012-02-08 16:29:25 -05:00
|
|
|
*buf += sizeof(cur->u.ReadWrite.len);
|
|
|
|
|
RtlCopyMemory(&cur->u.ReadWrite.ChangeTime, *buf, sizeof(ULONGLONG));
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("unmarshal_nfs41_rw: returned len %lu ChangeTime %llu\n",
|
2012-02-08 16:29:25 -05:00
|
|
|
cur->u.ReadWrite.len, cur->u.ReadWrite.ChangeTime);
|
2011-12-22 11:59:45 -05:00
|
|
|
#if 1
|
|
|
|
|
/* 08/27/2010: it looks like we really don't need to call
|
|
|
|
|
* MmUnmapLockedPages() eventhough we called
|
|
|
|
|
* MmMapLockedPagesSpecifyCache() as the MDL passed to us
|
|
|
|
|
* is already locked.
|
|
|
|
|
*/
|
|
|
|
|
__try {
|
|
|
|
|
MmUnmapLockedPages(cur->u.ReadWrite.buf, cur->u.ReadWrite.MdlAddress);
|
|
|
|
|
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
|
NTSTATUS code;
|
|
|
|
|
code = GetExceptionCode();
|
|
|
|
|
print_error("Call to MmUnmapLockedPages failed due to"
|
|
|
|
|
" exception 0x%0x\n", code);
|
|
|
|
|
status = STATUS_ACCESS_DENIED;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS unmarshal_nfs41_open(
|
|
|
|
|
nfs41_updowncall_entry *cur,
|
|
|
|
|
unsigned char **buf)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
|
|
RtlCopyMemory(&cur->u.Open.binfo, *buf, sizeof(FILE_BASIC_INFORMATION));
|
|
|
|
|
*buf += sizeof(FILE_BASIC_INFORMATION);
|
|
|
|
|
RtlCopyMemory(&cur->u.Open.sinfo, *buf, sizeof(FILE_STANDARD_INFORMATION));
|
|
|
|
|
*buf += sizeof(FILE_STANDARD_INFORMATION);
|
|
|
|
|
RtlCopyMemory(&cur->open_state, *buf, sizeof(HANDLE));
|
|
|
|
|
*buf += sizeof(HANDLE);
|
|
|
|
|
RtlCopyMemory(&cur->u.Open.mode, *buf, sizeof(DWORD));
|
|
|
|
|
*buf += sizeof(DWORD);
|
2012-02-08 11:11:09 -05:00
|
|
|
RtlCopyMemory(&cur->u.Open.changeattr, *buf, sizeof(ULONGLONG));
|
|
|
|
|
*buf += sizeof(ULONGLONG);
|
2012-01-20 15:01:11 -05:00
|
|
|
RtlCopyMemory(&cur->u.Open.deleg_type, *buf, sizeof(DWORD));
|
|
|
|
|
*buf += sizeof(DWORD);
|
2011-12-22 11:59:45 -05:00
|
|
|
if (cur->errno == ERROR_REPARSE) {
|
|
|
|
|
RtlCopyMemory(&cur->u.Open.symlink_embedded, *buf, sizeof(BOOLEAN));
|
|
|
|
|
*buf += sizeof(BOOLEAN);
|
|
|
|
|
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 = RxAllocatePoolWithTag(NonPagedPool,
|
|
|
|
|
cur->u.Open.symlink.MaximumLength, NFS41_MM_POOLTAG);
|
|
|
|
|
if (cur->u.Open.symlink.Buffer == NULL) {
|
|
|
|
|
cur->status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
status = STATUS_UNSUCCESSFUL;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
RtlCopyMemory(cur->u.Open.symlink.Buffer, *buf,
|
|
|
|
|
cur->u.Open.symlink.MaximumLength);
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("unmarshal_nfs41_open: ERROR_REPARSE -> '%wZ'\n", &cur->u.Open.symlink);
|
2011-12-22 11:59:45 -05:00
|
|
|
}
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("unmarshal_nfs41_open: open_state 0x%x mode %o changeattr %llu "
|
|
|
|
|
"deleg_type %d\n", cur->open_state, cur->u.Open.mode,
|
|
|
|
|
cur->u.Open.changeattr, cur->u.Open.deleg_type);
|
2011-12-22 11:59:45 -05:00
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS unmarshal_nfs41_dirquery(
|
|
|
|
|
nfs41_updowncall_entry *cur,
|
|
|
|
|
unsigned char **buf)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
ULONG buf_len;
|
|
|
|
|
|
|
|
|
|
RtlCopyMemory(&buf_len, *buf, sizeof(ULONG));
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("unmarshal_nfs41_dirquery: reply size %d\n", buf_len);
|
2011-12-22 11:59:45 -05:00
|
|
|
*buf += sizeof(ULONG);
|
|
|
|
|
__try {
|
|
|
|
|
MmUnmapLockedPages(cur->u.QueryFile.mdl_buf, cur->u.QueryFile.mdl);
|
|
|
|
|
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
|
NTSTATUS code;
|
|
|
|
|
code = GetExceptionCode();
|
|
|
|
|
print_error("MmUnmapLockedPages thrown exception=0x%0x\n", code);
|
|
|
|
|
status = STATUS_ACCESS_DENIED;
|
|
|
|
|
}
|
|
|
|
|
if (buf_len > cur->u.QueryFile.buf_len)
|
|
|
|
|
cur->status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
|
cur->u.QueryFile.buf_len = buf_len;
|
|
|
|
|
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void unmarshal_nfs41_attrget(
|
|
|
|
|
nfs41_updowncall_entry *cur,
|
|
|
|
|
PVOID attr_value,
|
|
|
|
|
ULONG *attr_len,
|
|
|
|
|
unsigned char **buf)
|
|
|
|
|
{
|
|
|
|
|
ULONG buf_len;
|
|
|
|
|
RtlCopyMemory(&buf_len, *buf, sizeof(ULONG));
|
|
|
|
|
if (buf_len > *attr_len) {
|
|
|
|
|
cur->status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-02-06 14:23:47 -05:00
|
|
|
*buf += sizeof(ULONG);
|
|
|
|
|
*attr_len = buf_len;
|
2011-12-22 11:59:45 -05:00
|
|
|
RtlCopyMemory(attr_value, *buf, buf_len);
|
2012-02-06 14:23:47 -05:00
|
|
|
*buf += buf_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void unmarshal_nfs41_getattr(
|
|
|
|
|
nfs41_updowncall_entry *cur,
|
|
|
|
|
unsigned char **buf)
|
|
|
|
|
{
|
|
|
|
|
unmarshal_nfs41_attrget(cur, cur->u.QueryFile.buf,
|
|
|
|
|
&cur->u.QueryFile.buf_len, buf);
|
|
|
|
|
RtlCopyMemory(&cur->u.QueryFile.ChangeTime, *buf, sizeof(LONGLONG));
|
2012-02-08 18:24:19 -05:00
|
|
|
if (cur->u.QueryFile.InfoClass == FileBasicInformation)
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("[unmarshal_nfs41_getattr] ChangeTime %llu\n", cur->u.QueryFile.ChangeTime);
|
2011-12-22 11:59:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS unmarshal_nfs41_getacl(
|
|
|
|
|
nfs41_updowncall_entry *cur,
|
|
|
|
|
unsigned char **buf)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
DWORD buf_len;
|
|
|
|
|
|
|
|
|
|
RtlCopyMemory(&buf_len, *buf, sizeof(DWORD));
|
|
|
|
|
*buf += sizeof(DWORD);
|
|
|
|
|
cur->u.Acl.buf = RxAllocatePoolWithTag(NonPagedPool,
|
|
|
|
|
buf_len, NFS41_MM_POOLTAG);
|
|
|
|
|
if (cur->u.Acl.buf == NULL) {
|
|
|
|
|
cur->status = status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
RtlCopyMemory(cur->u.Acl.buf, *buf, buf_len);
|
|
|
|
|
if (buf_len > cur->u.Acl.buf_len)
|
|
|
|
|
cur->status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
|
cur->u.Acl.buf_len = buf_len;
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void unmarshal_nfs41_symlink(
|
|
|
|
|
nfs41_updowncall_entry *cur,
|
|
|
|
|
unsigned char **buf)
|
|
|
|
|
{
|
|
|
|
|
if (cur->u.Symlink.set)
|
|
|
|
|
return;
|
|
|
|
|
RtlCopyMemory(&cur->u.Symlink.target->Length, *buf, sizeof(USHORT));
|
|
|
|
|
*buf += sizeof(USHORT);
|
|
|
|
|
if (cur->u.Symlink.target->Length >
|
|
|
|
|
cur->u.Symlink.target->MaximumLength) {
|
|
|
|
|
cur->status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
RtlCopyMemory(cur->u.Symlink.target->Buffer, *buf,
|
|
|
|
|
cur->u.Symlink.target->Length);
|
|
|
|
|
cur->u.Symlink.target->Length -= sizeof(UNICODE_NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_downcall(
|
|
|
|
|
IN PRX_CONTEXT RxContext)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
2010-10-11 14:59:26 -04:00
|
|
|
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
|
|
|
|
|
ULONG in_len = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
|
|
|
|
|
unsigned char *buf = LowIoContext->ParamsFor.IoCtl.pInputBuffer;
|
|
|
|
|
PLIST_ENTRY pEntry;
|
2011-12-21 15:53:17 -05:00
|
|
|
nfs41_updowncall_entry *tmp, *cur= NULL;
|
|
|
|
|
BOOLEAN found = 0;
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
print_hexbuf(0, (unsigned char *)"downcall buffer", buf, in_len);
|
|
|
|
|
|
|
|
|
|
tmp = RxAllocatePoolWithTag(NonPagedPool, sizeof(nfs41_updowncall_entry),
|
|
|
|
|
NFS41_MM_POOLTAG);
|
2011-12-21 15:53:17 -05:00
|
|
|
if (tmp == NULL)
|
2010-10-11 14:59:26 -04:00
|
|
|
goto out;
|
2011-12-21 15:53:17 -05:00
|
|
|
|
2011-12-22 11:59:45 -05:00
|
|
|
unmarshal_nfs41_header(tmp, &buf);
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
ExAcquireFastMutex(&downcallLock);
|
|
|
|
|
pEntry = &downcall->head;
|
2011-10-06 12:38:55 -04:00
|
|
|
pEntry = pEntry->Flink;
|
2010-10-11 14:59:26 -04:00
|
|
|
while (pEntry != NULL) {
|
|
|
|
|
cur = (nfs41_updowncall_entry *)CONTAINING_RECORD(pEntry,
|
|
|
|
|
nfs41_updowncall_entry, next);
|
|
|
|
|
if (cur->xid == tmp->xid) {
|
|
|
|
|
found = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-02-13 16:08:21 -05:00
|
|
|
if (pEntry->Flink == &downcall->head)
|
2010-10-11 14:59:26 -04:00
|
|
|
break;
|
|
|
|
|
pEntry = pEntry->Flink;
|
|
|
|
|
}
|
2011-12-21 16:15:26 -05:00
|
|
|
ExReleaseFastMutex(&downcallLock);
|
|
|
|
|
SeStopImpersonatingClient();
|
2010-10-11 14:59:26 -04:00
|
|
|
if (!found) {
|
2011-12-21 17:19:38 -05:00
|
|
|
print_error("Didn't find xid=%lld entry\n", tmp->xid);
|
2010-10-11 14:59:26 -04:00
|
|
|
goto out_free;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 16:15:26 -05:00
|
|
|
ExAcquireFastMutex(&cur->lock);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (cur->state == NFS41_NOT_WAITING) {
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("[downcall] Nobody is waiting for this request!!!\n");
|
2011-12-21 16:43:55 -05:00
|
|
|
switch(cur->opcode) {
|
|
|
|
|
case NFS41_WRITE:
|
|
|
|
|
case NFS41_READ:
|
|
|
|
|
MmUnmapLockedPages(cur->u.ReadWrite.buf,
|
|
|
|
|
cur->u.ReadWrite.MdlAddress);
|
|
|
|
|
break;
|
|
|
|
|
case NFS41_DIR_QUERY:
|
|
|
|
|
MmUnmapLockedPages(cur->u.QueryFile.mdl_buf,
|
|
|
|
|
cur->u.QueryFile.mdl);
|
|
|
|
|
IoFreeMdl(cur->u.QueryFile.mdl);
|
|
|
|
|
}
|
2011-12-21 15:53:17 -05:00
|
|
|
ExReleaseFastMutex(&cur->lock);
|
|
|
|
|
nfs41_RemoveEntry(downcallLock, downcall, cur);
|
|
|
|
|
RxFreePool(cur);
|
|
|
|
|
status = STATUS_UNSUCCESSFUL;
|
|
|
|
|
goto out_free;
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
cur->state = NFS41_DONE_PROCESSING;
|
|
|
|
|
cur->status = tmp->status;
|
|
|
|
|
cur->errno = tmp->errno;
|
2010-10-15 12:06:16 -04:00
|
|
|
status = STATUS_SUCCESS;
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
if (!tmp->status) {
|
|
|
|
|
switch (tmp->opcode) {
|
|
|
|
|
case NFS41_MOUNT:
|
2011-12-22 11:59:45 -05:00
|
|
|
unmarshal_nfs41_mount(cur, &buf);
|
2010-10-11 14:59:26 -04:00
|
|
|
break;
|
|
|
|
|
case NFS41_WRITE:
|
|
|
|
|
case NFS41_READ:
|
2011-12-22 11:59:45 -05:00
|
|
|
status = unmarshal_nfs41_rw(cur, &buf);
|
2010-10-11 14:59:26 -04:00
|
|
|
break;
|
|
|
|
|
case NFS41_OPEN:
|
2011-12-22 11:59:45 -05:00
|
|
|
status = unmarshal_nfs41_open(cur, &buf);
|
2010-10-11 14:59:26 -04:00
|
|
|
break;
|
|
|
|
|
case NFS41_DIR_QUERY:
|
2011-12-22 11:59:45 -05:00
|
|
|
status = unmarshal_nfs41_dirquery(cur, &buf);
|
2011-09-27 12:21:26 -04:00
|
|
|
break;
|
2010-10-11 14:59:26 -04:00
|
|
|
case NFS41_FILE_QUERY:
|
2012-02-06 14:23:47 -05:00
|
|
|
unmarshal_nfs41_getattr(cur, &buf);
|
2010-10-11 14:59:26 -04:00
|
|
|
break;
|
2011-09-22 14:56:11 -04:00
|
|
|
case NFS41_EA_GET:
|
2011-12-22 11:59:45 -05:00
|
|
|
unmarshal_nfs41_attrget(cur, cur->u.QueryEa.buf,
|
|
|
|
|
&cur->u.QueryEa.buf_len, &buf);
|
2011-09-22 14:56:11 -04:00
|
|
|
break;
|
2010-09-23 12:19:21 -04:00
|
|
|
case NFS41_SYMLINK:
|
2011-12-22 11:59:45 -05:00
|
|
|
unmarshal_nfs41_symlink(cur, &buf);
|
2010-09-23 12:19:21 -04:00
|
|
|
break;
|
2010-10-11 14:59:26 -04:00
|
|
|
case NFS41_VOLUME_QUERY:
|
2011-12-22 11:59:45 -05:00
|
|
|
unmarshal_nfs41_attrget(cur, cur->u.Volume.buf,
|
|
|
|
|
&cur->u.Volume.buf_len, &buf);
|
2010-10-11 14:59:26 -04:00
|
|
|
break;
|
2011-03-15 16:31:52 -04:00
|
|
|
case NFS41_ACL_QUERY:
|
2011-12-22 11:59:45 -05:00
|
|
|
status = unmarshal_nfs41_getacl(cur, &buf);
|
2011-03-15 16:31:52 -04:00
|
|
|
break;
|
2012-02-07 11:46:02 -05:00
|
|
|
case NFS41_FILE_SET:
|
|
|
|
|
unmarshal_nfs41_setattr(cur, &cur->u.SetFile.ChangeTime, &buf);
|
|
|
|
|
break;
|
|
|
|
|
case NFS41_EA_SET:
|
|
|
|
|
unmarshal_nfs41_setattr(cur, &cur->u.SetEa.ChangeTime, &buf);
|
|
|
|
|
break;
|
2012-02-06 14:22:38 -05:00
|
|
|
case NFS41_ACL_SET:
|
|
|
|
|
unmarshal_nfs41_setattr(cur, &cur->u.Acl.ChangeTime, &buf);
|
|
|
|
|
break;
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ExReleaseFastMutex(&cur->lock);
|
|
|
|
|
if (cur->async_op) {
|
|
|
|
|
if (cur->status == STATUS_SUCCESS) {
|
|
|
|
|
cur->u.ReadWrite.rxcontext->StoredStatus = STATUS_SUCCESS;
|
2011-12-21 15:53:17 -05:00
|
|
|
cur->u.ReadWrite.rxcontext->InformationToReturn =
|
|
|
|
|
cur->u.ReadWrite.len;
|
2010-10-11 14:59:26 -04:00
|
|
|
} else {
|
2011-12-21 15:53:17 -05:00
|
|
|
cur->u.ReadWrite.rxcontext->StoredStatus =
|
|
|
|
|
map_readwrite_errors(cur->status);
|
2010-10-11 14:59:26 -04:00
|
|
|
cur->u.ReadWrite.rxcontext->InformationToReturn = 0;
|
|
|
|
|
}
|
|
|
|
|
nfs41_RemoveEntry(downcallLock, downcall, cur);
|
|
|
|
|
RxLowIoCompletion(cur->u.ReadWrite.rxcontext);
|
|
|
|
|
} else
|
2010-10-15 12:06:16 -04:00
|
|
|
KeSetEvent(&cur->cond, 0, FALSE);
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
out_free:
|
|
|
|
|
RxFreePool(tmp);
|
|
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_shutdown_daemon(
|
|
|
|
|
DWORD version)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
nfs41_updowncall_entry *entry = NULL;
|
|
|
|
|
|
|
|
|
|
DbgEn();
|
2011-04-13 15:28:48 -04:00
|
|
|
status = nfs41_UpcallCreate(NFS41_SHUTDOWN, NULL, INVALID_HANDLE_VALUE,
|
2012-02-13 16:08:21 -05:00
|
|
|
INVALID_HANDLE_VALUE, version, NULL, &entry);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (status)
|
|
|
|
|
goto out;
|
|
|
|
|
|
2011-12-21 16:36:39 -05:00
|
|
|
status = nfs41_UpcallWaitForReply(entry);
|
|
|
|
|
SeDeleteClientSecurity(&entry->sec_ctx);
|
|
|
|
|
if (status != STATUS_SUCCESS) {
|
2010-10-11 14:59:26 -04:00
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
RxFreePool(entry);
|
|
|
|
|
out:
|
|
|
|
|
DbgEx();
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS SharedMemoryInit(
|
2010-10-11 14:59:26 -04:00
|
|
|
OUT PHANDLE phSection)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status;
|
|
|
|
|
HANDLE hSection;
|
|
|
|
|
UNICODE_STRING SectionName;
|
|
|
|
|
SECURITY_DESCRIPTOR SecurityDesc;
|
|
|
|
|
OBJECT_ATTRIBUTES SectionAttrs;
|
|
|
|
|
LARGE_INTEGER nSectionSize;
|
|
|
|
|
|
|
|
|
|
DbgEn();
|
|
|
|
|
|
|
|
|
|
RtlInitUnicodeString(&SectionName, NFS41_SHARED_MEMORY_NAME);
|
|
|
|
|
|
|
|
|
|
/* XXX: setting dacl=NULL grants access to everyone */
|
|
|
|
|
status = RtlCreateSecurityDescriptor(&SecurityDesc,
|
|
|
|
|
SECURITY_DESCRIPTOR_REVISION);
|
|
|
|
|
if (status) {
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("RtlCreateSecurityDescriptor() failed with %08X\n", status);
|
2010-10-11 14:59:26 -04:00
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
status = RtlSetDaclSecurityDescriptor(&SecurityDesc, TRUE, NULL, FALSE);
|
|
|
|
|
if (status) {
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("RtlSetDaclSecurityDescriptor() failed with %08X\n", status);
|
2010-10-11 14:59:26 -04:00
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InitializeObjectAttributes(&SectionAttrs, &SectionName,
|
|
|
|
|
0, NULL, &SecurityDesc);
|
|
|
|
|
|
|
|
|
|
nSectionSize.QuadPart = sizeof(NFS41NP_SHARED_MEMORY);
|
|
|
|
|
|
|
|
|
|
status = ZwCreateSection(&hSection, SECTION_MAP_READ | SECTION_MAP_WRITE,
|
|
|
|
|
&SectionAttrs, &nSectionSize, PAGE_READWRITE, SEC_COMMIT, NULL);
|
|
|
|
|
switch (status) {
|
|
|
|
|
case STATUS_SUCCESS:
|
|
|
|
|
break;
|
|
|
|
|
case STATUS_OBJECT_NAME_COLLISION:
|
|
|
|
|
DbgP("section already created; returning success\n");
|
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
|
goto out;
|
|
|
|
|
default:
|
|
|
|
|
DbgP("ZwCreateSection failed with %08X\n", status);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
out:
|
|
|
|
|
DbgEx();
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS SharedMemoryFree(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN HANDLE hSection)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status;
|
|
|
|
|
DbgEn();
|
|
|
|
|
status = ZwClose(hSection);
|
|
|
|
|
DbgEx();
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_Start(
|
2011-12-21 15:53:17 -05:00
|
|
|
IN OUT PRX_CONTEXT RxContext,
|
2010-10-11 14:59:26 -04:00
|
|
|
IN OUT PRDBSS_DEVICE_OBJECT dev)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status;
|
|
|
|
|
NFS41GetDeviceExtension(RxContext, DevExt);
|
|
|
|
|
|
|
|
|
|
DbgEn();
|
|
|
|
|
|
|
|
|
|
status = SharedMemoryInit(&DevExt->SharedMemorySection);
|
|
|
|
|
if (status) {
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("InitSharedMemory failed with %08X\n", status);
|
2010-10-11 14:59:26 -04:00
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InterlockedCompareExchange((PLONG)&nfs41_start_state,
|
|
|
|
|
NFS41_START_DRIVER_STARTED,
|
|
|
|
|
NFS41_START_DRIVER_START_IN_PROGRESS);
|
|
|
|
|
out:
|
|
|
|
|
DbgEx();
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_Stop(
|
2011-12-21 15:53:17 -05:00
|
|
|
IN OUT PRX_CONTEXT RxContext,
|
2010-10-11 14:59:26 -04:00
|
|
|
IN OUT PRDBSS_DEVICE_OBJECT dev)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status;
|
|
|
|
|
NFS41GetDeviceExtension(RxContext, DevExt);
|
|
|
|
|
DbgEn();
|
|
|
|
|
status = SharedMemoryFree(DevExt->SharedMemorySection);
|
|
|
|
|
DbgEx();
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS GetConnectionHandle(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN PUNICODE_STRING ConnectionName,
|
|
|
|
|
IN PVOID EaBuffer,
|
2011-10-19 09:07:20 -07:00
|
|
|
IN ULONG EaLength,
|
|
|
|
|
OUT PHANDLE Handle)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status;
|
|
|
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
|
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
InitializeObjectAttributes(&ObjectAttributes, ConnectionName,
|
|
|
|
|
OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, NULL, NULL);
|
|
|
|
|
|
2011-10-19 09:07:20 -07:00
|
|
|
status = ZwCreateFile(Handle, SYNCHRONIZE, &ObjectAttributes,
|
2010-10-11 14:59:26 -04:00
|
|
|
&IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL,
|
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
|
|
|
FILE_OPEN_IF,
|
|
|
|
|
FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
|
|
|
|
|
EaBuffer, EaLength);
|
|
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-10-19 09:07:20 -07:00
|
|
|
return status;
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_GetConnectionInfoFromBuffer(
|
|
|
|
|
IN PVOID Buffer,
|
|
|
|
|
IN ULONG BufferLen,
|
|
|
|
|
OUT PUNICODE_STRING pConnectionName,
|
|
|
|
|
OUT PVOID *ppEaBuffer,
|
|
|
|
|
OUT PULONG pEaLength)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
2011-12-21 15:53:17 -05:00
|
|
|
USHORT NameLength, EaPadding;
|
|
|
|
|
ULONG EaLength, BufferLenExpected;
|
2010-10-11 14:59:26 -04:00
|
|
|
PBYTE ptr;
|
|
|
|
|
|
|
|
|
|
/* make sure buffer is at least big enough for header */
|
2011-12-21 15:53:17 -05:00
|
|
|
if (BufferLen < sizeof(USHORT) + sizeof(USHORT) + sizeof(ULONG)) {
|
2010-10-11 14:59:26 -04:00
|
|
|
status = STATUS_BAD_NETWORK_NAME;
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("Invalid input buffer.\n");
|
2010-10-11 14:59:26 -04:00
|
|
|
pConnectionName->Length = pConnectionName->MaximumLength = 0;
|
|
|
|
|
*ppEaBuffer = NULL;
|
|
|
|
|
*pEaLength = 0;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ptr = Buffer;
|
|
|
|
|
NameLength = *(PUSHORT)ptr;
|
|
|
|
|
ptr += sizeof(USHORT);
|
|
|
|
|
EaPadding = *(PUSHORT)ptr;
|
|
|
|
|
ptr += sizeof(USHORT);
|
|
|
|
|
EaLength = *(PULONG)ptr;
|
|
|
|
|
ptr += sizeof(ULONG);
|
|
|
|
|
|
|
|
|
|
/* validate buffer length */
|
|
|
|
|
BufferLenExpected = sizeof(USHORT) + sizeof(USHORT) + sizeof(ULONG) +
|
|
|
|
|
NameLength + EaPadding + EaLength;
|
2011-12-21 15:53:17 -05:00
|
|
|
if (BufferLen != BufferLenExpected) {
|
2010-10-11 14:59:26 -04:00
|
|
|
status = STATUS_BAD_NETWORK_NAME;
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("Received buffer of length %lu, but expected %lu bytes.\n",
|
2010-10-11 14:59:26 -04:00
|
|
|
BufferLen, BufferLenExpected);
|
|
|
|
|
pConnectionName->Length = pConnectionName->MaximumLength = 0;
|
|
|
|
|
*ppEaBuffer = NULL;
|
|
|
|
|
*pEaLength = 0;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pConnectionName->Buffer = (PWCH)ptr;
|
|
|
|
|
pConnectionName->Length = NameLength - sizeof(WCHAR);
|
|
|
|
|
pConnectionName->MaximumLength = NameLength;
|
|
|
|
|
|
|
|
|
|
if (EaLength)
|
|
|
|
|
*ppEaBuffer = ptr + NameLength + EaPadding;
|
|
|
|
|
else
|
|
|
|
|
*ppEaBuffer = NULL;
|
|
|
|
|
*pEaLength = EaLength;
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_CreateConnection(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN PRX_CONTEXT RxContext,
|
2011-12-21 15:53:17 -05:00
|
|
|
OUT PBOOLEAN PostToFsp)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
HANDLE Handle = INVALID_HANDLE_VALUE;
|
2010-10-11 14:59:26 -04:00
|
|
|
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
|
2011-12-21 15:53:17 -05:00
|
|
|
PVOID Buffer = LowIoContext->ParamsFor.IoCtl.pInputBuffer, EaBuffer;
|
|
|
|
|
ULONG BufferLen = LowIoContext->ParamsFor.IoCtl.InputBufferLength, EaLength;
|
2010-10-11 14:59:26 -04:00
|
|
|
UNICODE_STRING FileName;
|
2011-12-21 15:53:17 -05:00
|
|
|
BOOLEAN Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
if (!Wait) {
|
|
|
|
|
//just post right now!
|
|
|
|
|
DbgP("returning STATUS_PENDING\n");
|
|
|
|
|
*PostToFsp = TRUE;
|
|
|
|
|
status = STATUS_PENDING;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
status = nfs41_GetConnectionInfoFromBuffer(Buffer, BufferLen,
|
|
|
|
|
&FileName, &EaBuffer, &EaLength);
|
|
|
|
|
if (status != STATUS_SUCCESS)
|
|
|
|
|
goto out;
|
|
|
|
|
|
2011-10-19 09:07:20 -07:00
|
|
|
status = GetConnectionHandle(&FileName, EaBuffer, EaLength, &Handle);
|
2011-10-31 15:25:28 -04:00
|
|
|
if (!status && Handle != INVALID_HANDLE_VALUE)
|
|
|
|
|
ZwClose(Handle);
|
2010-10-11 14:59:26 -04:00
|
|
|
out:
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
2011-12-21 15:53:17 -05:00
|
|
|
void print_op_stat(
|
|
|
|
|
const char *op_str,
|
|
|
|
|
nfs41_timings *time, BOOLEAN clear)
|
2011-09-06 18:01:17 -04:00
|
|
|
{
|
2011-09-22 14:56:11 -04:00
|
|
|
DbgP("%-9s: num_ops=%-10d delta_ticks=%-10d size=%-10d\n", op_str,
|
2011-09-06 18:01:17 -04:00
|
|
|
time->tops, time->tops ? time->ticks/time->tops : 0,
|
|
|
|
|
time->sops ? time->size/time->sops : 0);
|
|
|
|
|
if (clear) {
|
|
|
|
|
time->tops = 0;
|
|
|
|
|
time->ticks = 0;
|
|
|
|
|
time->size = 0;
|
|
|
|
|
time->sops = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_unmount(
|
|
|
|
|
HANDLE session,
|
|
|
|
|
DWORD version)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
|
2010-10-11 14:59:26 -04:00
|
|
|
nfs41_updowncall_entry *entry;
|
|
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-04-13 15:28:48 -04:00
|
|
|
status = nfs41_UpcallCreate(NFS41_UNMOUNT, NULL, session,
|
2012-02-13 16:08:21 -05:00
|
|
|
INVALID_HANDLE_VALUE, version, NULL, &entry);
|
2011-12-21 16:36:39 -05:00
|
|
|
SeDeleteClientSecurity(&entry->sec_ctx);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (status)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
if (nfs41_UpcallWaitForReply(entry) != STATUS_SUCCESS) {
|
|
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
RxFreePool(entry);
|
|
|
|
|
out:
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
print_op_stat("lookup", &lookup, 1);
|
|
|
|
|
print_op_stat("open", &open, 1);
|
|
|
|
|
print_op_stat("close", &close, 1);
|
|
|
|
|
print_op_stat("volume", &volume, 1);
|
|
|
|
|
print_op_stat("getattr", &getattr, 1);
|
|
|
|
|
print_op_stat("setattr", &setattr, 1);
|
2011-09-22 14:56:11 -04:00
|
|
|
print_op_stat("getexattr", &getexattr, 1);
|
|
|
|
|
print_op_stat("setexattr", &setexattr, 1);
|
2011-09-06 18:01:17 -04:00
|
|
|
print_op_stat("readdir", &readdir, 1);
|
|
|
|
|
print_op_stat("getacl", &getacl, 1);
|
|
|
|
|
print_op_stat("setacl", &setacl, 1);
|
|
|
|
|
print_op_stat("read", &read, 1);
|
|
|
|
|
print_op_stat("write", &write, 1);
|
|
|
|
|
print_op_stat("lock", &lock, 1);
|
|
|
|
|
print_op_stat("unlock", &unlock, 1);
|
|
|
|
|
#endif
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_DeleteConnection (
|
2010-10-11 14:59:26 -04:00
|
|
|
IN PRX_CONTEXT RxContext,
|
2011-12-21 15:53:17 -05:00
|
|
|
OUT PBOOLEAN PostToFsp)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_INVALID_PARAMETER;
|
|
|
|
|
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
|
|
|
|
|
PWCHAR ConnectName = LowIoContext->ParamsFor.IoCtl.pInputBuffer;
|
|
|
|
|
ULONG ConnectNameLen = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
|
|
|
|
|
HANDLE Handle;
|
|
|
|
|
UNICODE_STRING FileName;
|
|
|
|
|
PFILE_OBJECT pFileObject;
|
|
|
|
|
BOOLEAN Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
|
|
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
if (!Wait) {
|
|
|
|
|
//just post right now!
|
|
|
|
|
*PostToFsp = TRUE;
|
|
|
|
|
DbgP("returning STATUS_PENDING\n");
|
|
|
|
|
status = STATUS_PENDING;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FileName.Buffer = ConnectName;
|
|
|
|
|
FileName.Length = (USHORT) ConnectNameLen - sizeof(WCHAR);
|
|
|
|
|
FileName.MaximumLength = (USHORT) ConnectNameLen;
|
|
|
|
|
|
2011-10-19 09:07:20 -07:00
|
|
|
status = GetConnectionHandle(&FileName, NULL, 0, &Handle);
|
|
|
|
|
if (status != STATUS_SUCCESS)
|
2010-10-11 14:59:26 -04:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
status = ObReferenceObjectByHandle(Handle, 0L, NULL, KernelMode,
|
|
|
|
|
(PVOID *)&pFileObject, NULL);
|
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
|
PV_NET_ROOT VNetRoot;
|
|
|
|
|
|
|
|
|
|
// VNetRoot exists as FOBx in the FsContext2
|
|
|
|
|
VNetRoot = (PV_NET_ROOT) pFileObject->FsContext2;
|
|
|
|
|
// make sure the node looks right
|
|
|
|
|
if (NodeType(VNetRoot) == RDBSS_NTC_V_NETROOT)
|
|
|
|
|
{
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgP("Calling RxFinalizeConnection for NetRoot %p from VNetRoot %p\n",
|
2010-11-05 15:36:10 -04:00
|
|
|
VNetRoot->NetRoot, VNetRoot);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
status = RxFinalizeConnection(VNetRoot->NetRoot, VNetRoot, TRUE);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
status = STATUS_BAD_NETWORK_NAME;
|
|
|
|
|
|
|
|
|
|
ObDereferenceObject(pFileObject);
|
|
|
|
|
}
|
|
|
|
|
ZwClose(Handle);
|
|
|
|
|
out:
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_DevFcbXXXControlFile(
|
|
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
|
UCHAR op = RxContext->MajorFunction;
|
|
|
|
|
PLOWIO_CONTEXT io_ctx = &RxContext->LowIoContext;
|
2011-12-21 15:53:17 -05:00
|
|
|
ULONG fsop = io_ctx->ParamsFor.FsCtl.FsControlCode, state;
|
2010-11-05 20:08:55 -04:00
|
|
|
ULONG in_len = io_ctx->ParamsFor.IoCtl.InputBufferLength;
|
|
|
|
|
DWORD *buf = io_ctx->ParamsFor.IoCtl.pInputBuffer;
|
|
|
|
|
NFS41GetDeviceExtension(RxContext, DevExt);
|
|
|
|
|
DWORD nfs41d_version = 0;
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
//DbgEn();
|
|
|
|
|
|
|
|
|
|
print_ioctl(0, op);
|
|
|
|
|
switch(op) {
|
|
|
|
|
case IRP_MJ_FILE_SYSTEM_CONTROL:
|
|
|
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
|
break;
|
|
|
|
|
case IRP_MJ_DEVICE_CONTROL:
|
|
|
|
|
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
|
|
|
|
|
print_fs_ioctl(0, fsop);
|
|
|
|
|
switch (fsop) {
|
|
|
|
|
case IOCTL_NFS41_INVALCACHE:
|
|
|
|
|
status = nfs41_invalidate_cache(RxContext);
|
|
|
|
|
break;
|
|
|
|
|
case IOCTL_NFS41_READ:
|
|
|
|
|
status = nfs41_upcall(RxContext);
|
|
|
|
|
break;
|
|
|
|
|
case IOCTL_NFS41_WRITE:
|
|
|
|
|
status = nfs41_downcall(RxContext);
|
|
|
|
|
break;
|
|
|
|
|
case IOCTL_NFS41_ADDCONN:
|
|
|
|
|
status = nfs41_CreateConnection(RxContext, &RxContext->PostRequest);
|
|
|
|
|
break;
|
|
|
|
|
case IOCTL_NFS41_DELCONN:
|
2010-12-15 16:15:29 -05:00
|
|
|
if (RxContext->RxDeviceObject->NumberOfActiveFcbs > 0) {
|
|
|
|
|
DbgP("device has open handles %d\n",
|
|
|
|
|
RxContext->RxDeviceObject->NumberOfActiveFcbs);
|
|
|
|
|
status = STATUS_REDIRECTOR_HAS_OPEN_HANDLES;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2010-10-11 14:59:26 -04:00
|
|
|
status = nfs41_DeleteConnection(RxContext, &RxContext->PostRequest);
|
|
|
|
|
break;
|
|
|
|
|
case IOCTL_NFS41_GETSTATE:
|
|
|
|
|
state = RDR_NULL_STATE;
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
if (io_ctx->ParamsFor.IoCtl.OutputBufferLength >= sizeof(ULONG)) {
|
2010-10-11 14:59:26 -04:00
|
|
|
// map the states to control app's equivalents
|
|
|
|
|
print_driver_state(nfs41_start_state);
|
|
|
|
|
switch (nfs41_start_state) {
|
|
|
|
|
case NFS41_START_DRIVER_STARTABLE:
|
|
|
|
|
case NFS41_START_DRIVER_STOPPED:
|
|
|
|
|
state = RDR_STOPPED;
|
|
|
|
|
break;
|
|
|
|
|
case NFS41_START_DRIVER_START_IN_PROGRESS:
|
|
|
|
|
state = RDR_STARTING;
|
|
|
|
|
break;
|
|
|
|
|
case NFS41_START_DRIVER_STARTED:
|
|
|
|
|
state = RDR_STARTED;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
*(ULONG *)io_ctx->ParamsFor.IoCtl.pOutputBuffer = state;
|
|
|
|
|
RxContext->InformationToReturn = sizeof(ULONG);
|
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
|
} else
|
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
|
|
|
break;
|
|
|
|
|
case IOCTL_NFS41_START:
|
|
|
|
|
print_driver_state(nfs41_start_state);
|
2010-11-05 20:08:55 -04:00
|
|
|
if (in_len >= sizeof(DWORD)) {
|
|
|
|
|
RtlCopyMemory(&nfs41d_version, buf, sizeof(DWORD));
|
2011-12-21 15:53:17 -05:00
|
|
|
DbgP("NFS41 Daemon sent start request with version %d\n",
|
|
|
|
|
nfs41d_version);
|
|
|
|
|
DbgP("Currently used NFS41 Daemon version is %d\n",
|
|
|
|
|
DevExt->nfs41d_version);
|
2010-11-05 20:08:55 -04:00
|
|
|
DevExt->nfs41d_version = nfs41d_version;
|
|
|
|
|
}
|
2010-10-11 14:59:26 -04:00
|
|
|
switch(nfs41_start_state) {
|
|
|
|
|
case NFS41_START_DRIVER_STARTABLE:
|
|
|
|
|
(nfs41_start_driver_state)InterlockedCompareExchange(
|
|
|
|
|
(PLONG)&nfs41_start_state,
|
|
|
|
|
NFS41_START_DRIVER_START_IN_PROGRESS,
|
|
|
|
|
NFS41_START_DRIVER_STARTABLE);
|
|
|
|
|
//lack of break is intentional
|
|
|
|
|
case NFS41_START_DRIVER_START_IN_PROGRESS:
|
|
|
|
|
status = RxStartMinirdr(RxContext, &RxContext->PostRequest);
|
|
|
|
|
if (status == STATUS_REDIRECTOR_STARTED) {
|
|
|
|
|
DbgP("redirector started\n");
|
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
|
} else if (status == STATUS_PENDING &&
|
|
|
|
|
RxContext->PostRequest == TRUE) {
|
|
|
|
|
DbgP("RxStartMinirdr pending %08lx\n", status);
|
|
|
|
|
status = STATUS_MORE_PROCESSING_REQUIRED;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case NFS41_START_DRIVER_STARTED:
|
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case IOCTL_NFS41_STOP:
|
|
|
|
|
if (nfs41_start_state == NFS41_START_DRIVER_STARTED)
|
2010-11-05 20:08:55 -04:00
|
|
|
nfs41_shutdown_daemon(DevExt->nfs41d_version);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (RxContext->RxDeviceObject->NumberOfActiveFcbs > 0) {
|
|
|
|
|
DbgP("device has open handles %d\n",
|
|
|
|
|
RxContext->RxDeviceObject->NumberOfActiveFcbs);
|
|
|
|
|
status = STATUS_REDIRECTOR_HAS_OPEN_HANDLES;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
state = (nfs41_start_driver_state)InterlockedCompareExchange(
|
|
|
|
|
(PLONG)&nfs41_start_state,
|
|
|
|
|
NFS41_START_DRIVER_STARTABLE,
|
|
|
|
|
NFS41_START_DRIVER_STARTED);
|
|
|
|
|
|
|
|
|
|
status = RxStopMinirdr(RxContext, &RxContext->PostRequest);
|
|
|
|
|
DbgP("RxStopMinirdr status %08lx\n", status);
|
|
|
|
|
if (status == STATUS_PENDING && RxContext->PostRequest == TRUE )
|
|
|
|
|
status = STATUS_MORE_PROCESSING_REQUIRED;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
|
};
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//DbgEx();
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS _nfs41_CreateSrvCall(
|
|
|
|
|
PMRX_SRVCALL_CALLBACK_CONTEXT pCallbackContext)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
2010-10-11 14:59:26 -04:00
|
|
|
PMRX_SRVCALL_CALLBACK_CONTEXT SCCBC = pCallbackContext;
|
|
|
|
|
PMRX_SRV_CALL pSrvCall;
|
|
|
|
|
PMRX_SRVCALLDOWN_STRUCTURE SrvCalldownStructure =
|
|
|
|
|
(PMRX_SRVCALLDOWN_STRUCTURE)(SCCBC->SrvCalldownStructure);
|
|
|
|
|
PNFS41_SERVER_ENTRY pServerEntry = NULL;
|
|
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
pSrvCall = SrvCalldownStructure->SrvCall;
|
|
|
|
|
|
|
|
|
|
ASSERT( pSrvCall );
|
|
|
|
|
ASSERT( NodeType(pSrvCall) == RDBSS_NTC_SRVCALL );
|
|
|
|
|
print_srv_call(0, pSrvCall);
|
|
|
|
|
|
|
|
|
|
// validate the server name with the test name of 'pnfs'
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgP("SrvCall: Connection Name Length: %d %wZ\n",
|
|
|
|
|
pSrvCall->pSrvCallName->Length, pSrvCall->pSrvCallName);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
if (pSrvCall->pSrvCallName->Length > SERVER_NAME_BUFFER_SIZE) {
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("Server name '%wZ' too long for server entry (max %u)\n",
|
2010-10-11 14:59:26 -04:00
|
|
|
pSrvCall->pSrvCallName, SERVER_NAME_BUFFER_SIZE);
|
|
|
|
|
status = STATUS_NAME_TOO_LONG;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Let's create our own representation of the server */
|
|
|
|
|
pServerEntry = (PNFS41_SERVER_ENTRY)RxAllocatePoolWithTag(PagedPool,
|
|
|
|
|
sizeof(NFS41_SERVER_ENTRY), NFS41_MM_POOLTAG);
|
|
|
|
|
if (pServerEntry == NULL) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
RtlZeroMemory(pServerEntry, sizeof(NFS41_SERVER_ENTRY));
|
|
|
|
|
|
|
|
|
|
pServerEntry->Name.Buffer = pServerEntry->NameBuffer;
|
|
|
|
|
pServerEntry->Name.Length = pSrvCall->pSrvCallName->Length;
|
|
|
|
|
pServerEntry->Name.MaximumLength = SERVER_NAME_BUFFER_SIZE;
|
|
|
|
|
RtlCopyMemory(pServerEntry->Name.Buffer, pSrvCall->pSrvCallName->Buffer,
|
|
|
|
|
pServerEntry->Name.Length);
|
|
|
|
|
|
|
|
|
|
pCallbackContext->RecommunicateContext = pServerEntry;
|
|
|
|
|
InterlockedExchangePointer(&pServerEntry->pRdbssSrvCall, pSrvCall);
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
SCCBC->Status = status;
|
|
|
|
|
SrvCalldownStructure->CallBack(SCCBC);
|
|
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_CreateSrvCall(
|
|
|
|
|
PMRX_SRV_CALL pSrvCall,
|
|
|
|
|
PMRX_SRVCALL_CALLBACK_CONTEXT pCallbackContext)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status;
|
|
|
|
|
|
|
|
|
|
ASSERT( pSrvCall );
|
|
|
|
|
ASSERT( NodeType(pSrvCall) == RDBSS_NTC_SRVCALL );
|
|
|
|
|
|
|
|
|
|
if (IoGetCurrentProcess() == RxGetRDBSSProcess()) {
|
|
|
|
|
DbgP("executing with RDBSS context\n");
|
|
|
|
|
status = _nfs41_CreateSrvCall(pCallbackContext);
|
|
|
|
|
} else {
|
|
|
|
|
status = RxDispatchToWorkerThread(nfs41_dev, DelayedWorkQueue,
|
|
|
|
|
_nfs41_CreateSrvCall, pCallbackContext);
|
|
|
|
|
if (status != STATUS_SUCCESS) {
|
2011-12-21 15:53:17 -05:00
|
|
|
print_error("RxDispatchToWorkerThread returned status %08lx\n",
|
|
|
|
|
status);
|
2010-10-11 14:59:26 -04:00
|
|
|
pCallbackContext->Status = status;
|
|
|
|
|
pCallbackContext->SrvCalldownStructure->CallBack(pCallbackContext);
|
|
|
|
|
status = STATUS_PENDING;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* RDBSS expects MRxCreateSrvCall to return STATUS_PENDING */
|
2012-02-13 16:08:21 -05:00
|
|
|
if (status == STATUS_SUCCESS)
|
2010-10-11 14:59:26 -04:00
|
|
|
status = STATUS_PENDING;
|
|
|
|
|
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_SrvCallWinnerNotify(
|
|
|
|
|
IN OUT PMRX_SRV_CALL pSrvCall,
|
|
|
|
|
IN BOOLEAN ThisMinirdrIsTheWinner,
|
|
|
|
|
IN OUT PVOID pSrvCallContext)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
PNFS41_SERVER_ENTRY pServerEntry;
|
|
|
|
|
|
|
|
|
|
pServerEntry = (PNFS41_SERVER_ENTRY)pSrvCallContext;
|
|
|
|
|
|
|
|
|
|
if (!ThisMinirdrIsTheWinner) {
|
|
|
|
|
ASSERT(1);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pSrvCall->Context = pServerEntry;
|
|
|
|
|
out:
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS map_mount_errors(
|
|
|
|
|
DWORD status)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
switch (status) {
|
|
|
|
|
case NO_ERROR: return STATUS_SUCCESS;
|
2011-10-19 09:07:20 -07:00
|
|
|
case ERROR_NETWORK_UNREACHABLE: return STATUS_NETWORK_UNREACHABLE;
|
2010-10-11 14:59:26 -04:00
|
|
|
case ERROR_BAD_NET_RESP: return STATUS_UNEXPECTED_NETWORK_ERROR;
|
2011-10-19 09:07:20 -07:00
|
|
|
case ERROR_BAD_NET_NAME: return STATUS_BAD_NETWORK_NAME;
|
2010-10-11 14:59:26 -04:00
|
|
|
case ERROR_BAD_NETPATH: return STATUS_BAD_NETWORK_PATH;
|
|
|
|
|
default:
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("failed to map windows error %d to NTSTATUS; "
|
2010-10-11 14:59:26 -04:00
|
|
|
"defaulting to STATUS_INSUFFICIENT_RESOURCES\n", status);
|
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_mount(
|
|
|
|
|
PNFS41_MOUNT_CONFIG config,
|
|
|
|
|
DWORD sec_flavor,
|
|
|
|
|
PHANDLE session,
|
|
|
|
|
DWORD *version)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
|
2010-10-11 14:59:26 -04:00
|
|
|
nfs41_updowncall_entry *entry;
|
|
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("Server Name %wZ Mount Point %wZ SecFlavor %wZ\n",
|
|
|
|
|
config->SrvName, config->MntPt, sec_flavor);
|
|
|
|
|
#endif
|
2011-04-13 15:28:48 -04:00
|
|
|
status = nfs41_UpcallCreate(NFS41_MOUNT, NULL, INVALID_HANDLE_VALUE,
|
2012-02-13 16:08:21 -05:00
|
|
|
INVALID_HANDLE_VALUE, *version, &config->MntPt, &entry);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (status)
|
|
|
|
|
goto out;
|
2011-10-11 16:03:59 -04:00
|
|
|
entry->u.Mount.srv_name = &config->SrvName;
|
|
|
|
|
entry->u.Mount.root = &config->MntPt;
|
|
|
|
|
entry->u.Mount.rsize = config->ReadSize;
|
|
|
|
|
entry->u.Mount.wsize = config->WriteSize;
|
2010-12-01 19:11:47 -05:00
|
|
|
entry->u.Mount.sec_flavor = sec_flavor;
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2011-12-21 16:36:39 -05:00
|
|
|
status = nfs41_UpcallWaitForReply(entry);
|
|
|
|
|
SeDeleteClientSecurity(&entry->sec_ctx);
|
|
|
|
|
if (status != STATUS_SUCCESS) {
|
2010-10-11 14:59:26 -04:00
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2011-04-13 15:28:48 -04:00
|
|
|
*session = entry->session;
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
/* map windows ERRORs to NTSTATUS */
|
|
|
|
|
status = map_mount_errors(entry->status);
|
2010-11-05 20:08:55 -04:00
|
|
|
if (status == STATUS_SUCCESS)
|
|
|
|
|
*version = entry->version;
|
2010-10-11 14:59:26 -04:00
|
|
|
RxFreePool(entry);
|
|
|
|
|
out:
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* TODO: move mount config stuff to another file -cbodley */
|
|
|
|
|
|
|
|
|
|
void nfs41_MountConfig_InitDefaults(
|
|
|
|
|
OUT PNFS41_MOUNT_CONFIG Config)
|
|
|
|
|
{
|
|
|
|
|
RtlZeroMemory(Config, sizeof(NFS41_MOUNT_CONFIG));
|
|
|
|
|
|
|
|
|
|
Config->ReadSize = MOUNT_CONFIG_RW_SIZE_DEFAULT;
|
|
|
|
|
Config->WriteSize = MOUNT_CONFIG_RW_SIZE_DEFAULT;
|
|
|
|
|
Config->ReadOnly = FALSE;
|
2011-12-07 18:10:09 -05:00
|
|
|
Config->write_thru = FALSE;
|
2011-12-08 17:47:34 -05:00
|
|
|
Config->nocache = FALSE;
|
2010-10-12 09:46:34 -04:00
|
|
|
Config->SrvName.Length = 0;
|
2010-10-11 14:59:26 -04:00
|
|
|
Config->SrvName.MaximumLength = SERVER_NAME_BUFFER_SIZE;
|
|
|
|
|
Config->SrvName.Buffer = Config->srv_buffer;
|
2010-10-12 09:46:34 -04:00
|
|
|
Config->MntPt.Length = 0;
|
2010-10-11 14:59:26 -04:00
|
|
|
Config->MntPt.MaximumLength = MAX_PATH;
|
|
|
|
|
Config->MntPt.Buffer = Config->mntpt_buffer;
|
2010-12-01 19:11:47 -05:00
|
|
|
Config->SecFlavor.Length = 0;
|
|
|
|
|
Config->SecFlavor.MaximumLength = MAX_SEC_FLAVOR_LEN;
|
|
|
|
|
Config->SecFlavor.Buffer = Config->sec_flavor;
|
|
|
|
|
RtlCopyUnicodeString(&Config->SecFlavor, &AUTH_SYS_NAME);
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_MountConfig_ParseBoolean(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN PFILE_FULL_EA_INFORMATION Option,
|
|
|
|
|
IN PUNICODE_STRING usValue,
|
|
|
|
|
OUT PBOOLEAN Value)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
|
|
/* if no value is specified, assume TRUE
|
|
|
|
|
* if a value is specified, it must be a '1' */
|
|
|
|
|
if (Option->EaValueLength == 0 || *usValue->Buffer == L'1')
|
|
|
|
|
*Value = TRUE;
|
|
|
|
|
else
|
|
|
|
|
*Value = FALSE;
|
|
|
|
|
|
|
|
|
|
DbgP(" '%ls' -> '%wZ' -> %u\n",
|
|
|
|
|
(LPWSTR)Option->EaName, *usValue, *Value);
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_MountConfig_ParseDword(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN PFILE_FULL_EA_INFORMATION Option,
|
|
|
|
|
IN PUNICODE_STRING usValue,
|
|
|
|
|
OUT PDWORD Value,
|
|
|
|
|
IN DWORD Minimum,
|
|
|
|
|
IN DWORD Maximum)
|
|
|
|
|
{
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS status = STATUS_INVALID_PARAMETER;
|
2010-10-11 14:59:26 -04:00
|
|
|
LPWSTR Name = (LPWSTR)Option->EaName;
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
if (Option->EaValueLength) {
|
2010-10-11 14:59:26 -04:00
|
|
|
status = RtlUnicodeStringToInteger(usValue, 0, Value);
|
2011-12-21 15:53:17 -05:00
|
|
|
if (status == STATUS_SUCCESS) {
|
2011-10-11 16:03:59 -04:00
|
|
|
#ifdef IMPOSE_MINMAX_RWSIZES
|
2010-10-11 14:59:26 -04:00
|
|
|
if (*Value < Minimum)
|
|
|
|
|
*Value = Minimum;
|
|
|
|
|
if (*Value > Maximum)
|
|
|
|
|
*Value = Maximum;
|
|
|
|
|
DbgP(" '%ls' -> '%wZ' -> %lu\n", Name, *usValue, *Value);
|
2011-10-11 16:03:59 -04:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
else
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("Failed to convert %s='%wZ' to unsigned long.\n",
|
2010-10-11 14:59:26 -04:00
|
|
|
Name, *usValue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_MountConfig_ParseOptions(
|
|
|
|
|
IN PFILE_FULL_EA_INFORMATION EaBuffer,
|
|
|
|
|
IN ULONG EaLength,
|
|
|
|
|
IN OUT PNFS41_MOUNT_CONFIG Config)
|
|
|
|
|
{
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
2010-10-11 14:59:26 -04:00
|
|
|
PFILE_FULL_EA_INFORMATION Option;
|
2011-12-21 15:53:17 -05:00
|
|
|
LPWSTR Name;
|
|
|
|
|
size_t NameLen;
|
2010-10-11 14:59:26 -04:00
|
|
|
UNICODE_STRING usValue;
|
|
|
|
|
Option = EaBuffer;
|
2011-12-21 15:53:17 -05:00
|
|
|
while (status == STATUS_SUCCESS) {
|
2010-10-11 14:59:26 -04:00
|
|
|
Name = (LPWSTR)Option->EaName;
|
|
|
|
|
NameLen = Option->EaNameLength/sizeof(WCHAR);
|
|
|
|
|
|
|
|
|
|
usValue.Length = usValue.MaximumLength = Option->EaValueLength;
|
|
|
|
|
usValue.Buffer = (PWCH)(Option->EaName +
|
|
|
|
|
Option->EaNameLength + sizeof(WCHAR));
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
if (wcsncmp(L"ro", Name, NameLen) == 0) {
|
2010-10-11 14:59:26 -04:00
|
|
|
status = nfs41_MountConfig_ParseBoolean(Option, &usValue,
|
|
|
|
|
&Config->ReadOnly);
|
|
|
|
|
}
|
2011-12-21 15:53:17 -05:00
|
|
|
else if (wcsncmp(L"writethru", Name, NameLen) == 0) {
|
2011-12-07 18:10:09 -05:00
|
|
|
status = nfs41_MountConfig_ParseBoolean(Option, &usValue,
|
|
|
|
|
&Config->write_thru);
|
|
|
|
|
}
|
2011-12-21 15:53:17 -05:00
|
|
|
else if (wcsncmp(L"nocache", Name, NameLen) == 0) {
|
2011-12-08 17:47:34 -05:00
|
|
|
status = nfs41_MountConfig_ParseBoolean(Option, &usValue,
|
|
|
|
|
&Config->nocache);
|
|
|
|
|
}
|
2011-12-21 15:53:17 -05:00
|
|
|
else if (wcsncmp(L"rsize", Name, NameLen) == 0) {
|
2010-10-11 14:59:26 -04:00
|
|
|
status = nfs41_MountConfig_ParseDword(Option, &usValue,
|
|
|
|
|
&Config->ReadSize, MOUNT_CONFIG_RW_SIZE_MIN,
|
|
|
|
|
MOUNT_CONFIG_RW_SIZE_MAX);
|
|
|
|
|
}
|
2011-12-21 15:53:17 -05:00
|
|
|
else if (wcsncmp(L"wsize", Name, NameLen) == 0) {
|
2010-10-11 14:59:26 -04:00
|
|
|
status = nfs41_MountConfig_ParseDword(Option, &usValue,
|
|
|
|
|
&Config->WriteSize, MOUNT_CONFIG_RW_SIZE_MIN,
|
|
|
|
|
MOUNT_CONFIG_RW_SIZE_MAX);
|
|
|
|
|
}
|
2011-12-21 15:53:17 -05:00
|
|
|
else if (wcsncmp(L"srvname", Name, NameLen) == 0) {
|
2010-10-11 14:59:26 -04:00
|
|
|
if (usValue.Length > Config->SrvName.MaximumLength)
|
|
|
|
|
status = STATUS_NAME_TOO_LONG;
|
|
|
|
|
else
|
|
|
|
|
RtlCopyUnicodeString(&Config->SrvName, &usValue);
|
|
|
|
|
}
|
2011-12-21 15:53:17 -05:00
|
|
|
else if (wcsncmp(L"mntpt", Name, NameLen) == 0) {
|
2010-10-11 14:59:26 -04:00
|
|
|
if (usValue.Length > Config->MntPt.MaximumLength)
|
|
|
|
|
status = STATUS_NAME_TOO_LONG;
|
|
|
|
|
else
|
|
|
|
|
RtlCopyUnicodeString(&Config->MntPt, &usValue);
|
|
|
|
|
}
|
2011-12-21 15:53:17 -05:00
|
|
|
else if (wcsncmp(L"sec", Name, NameLen) == 0) {
|
2010-12-01 19:11:47 -05:00
|
|
|
if (usValue.Length > Config->SecFlavor.MaximumLength)
|
|
|
|
|
status = STATUS_NAME_TOO_LONG;
|
|
|
|
|
else
|
|
|
|
|
RtlCopyUnicodeString(&Config->SecFlavor, &usValue);
|
|
|
|
|
}
|
2011-12-21 15:53:17 -05:00
|
|
|
else {
|
2010-10-11 14:59:26 -04:00
|
|
|
status = STATUS_INVALID_PARAMETER;
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("Unrecognized option '%ls' -> '%wZ'\n",
|
2010-10-11 14:59:26 -04:00
|
|
|
Name, usValue);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Option->NextEntryOffset == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
Option = (PFILE_FULL_EA_INFORMATION)
|
|
|
|
|
((PBYTE)Option + Option->NextEntryOffset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS has_nfs_prefix(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN PUNICODE_STRING SrvCallName,
|
|
|
|
|
IN PUNICODE_STRING NetRootName)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_BAD_NETWORK_NAME;
|
|
|
|
|
|
2011-04-20 11:58:16 -04:00
|
|
|
if (NetRootName->Length == SrvCallName->Length + NfsPrefix.Length) {
|
2010-10-11 14:59:26 -04:00
|
|
|
const UNICODE_STRING NetRootPrefix = {
|
|
|
|
|
NfsPrefix.Length,
|
|
|
|
|
NetRootName->MaximumLength - SrvCallName->Length,
|
|
|
|
|
&NetRootName->Buffer[SrvCallName->Length/2]
|
|
|
|
|
};
|
|
|
|
|
if (RtlCompareUnicodeString(&NetRootPrefix, &NfsPrefix, FALSE) == 0)
|
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS map_sec_flavor(
|
2010-12-01 19:11:47 -05:00
|
|
|
IN PUNICODE_STRING sec_flavor_name,
|
|
|
|
|
OUT PDWORD sec_flavor)
|
|
|
|
|
{
|
|
|
|
|
if (RtlCompareUnicodeString(sec_flavor_name, &AUTH_SYS_NAME, FALSE) == 0)
|
|
|
|
|
*sec_flavor = RPCSEC_AUTH_SYS;
|
|
|
|
|
else if (RtlCompareUnicodeString(sec_flavor_name, &AUTHGSS_KRB5_NAME, FALSE) == 0)
|
|
|
|
|
*sec_flavor = RPCSEC_AUTHGSS_KRB5;
|
|
|
|
|
else if (RtlCompareUnicodeString(sec_flavor_name, &AUTHGSS_KRB5I_NAME, FALSE) == 0)
|
|
|
|
|
*sec_flavor = RPCSEC_AUTHGSS_KRB5I;
|
|
|
|
|
else if (RtlCompareUnicodeString(sec_flavor_name, &AUTHGSS_KRB5P_NAME, FALSE) == 0)
|
|
|
|
|
*sec_flavor = RPCSEC_AUTHGSS_KRB5P;
|
|
|
|
|
else return STATUS_INVALID_PARAMETER;
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_GetLUID(
|
|
|
|
|
PLUID id)
|
2011-09-29 18:45:21 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
SECURITY_SUBJECT_CONTEXT sec_ctx;
|
|
|
|
|
SECURITY_QUALITY_OF_SERVICE sec_qos;
|
|
|
|
|
SECURITY_CLIENT_CONTEXT clnt_sec_ctx;
|
|
|
|
|
|
|
|
|
|
SeCaptureSubjectContext(&sec_ctx);
|
|
|
|
|
sec_qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
|
2011-12-21 15:53:17 -05:00
|
|
|
sec_qos.ImpersonationLevel = SecurityIdentification;
|
2011-09-29 18:45:21 -04:00
|
|
|
sec_qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
|
|
|
|
|
sec_qos.EffectiveOnly = 0;
|
2011-12-21 15:53:17 -05:00
|
|
|
status = SeCreateClientSecurityFromSubjectContext(&sec_ctx, &sec_qos, 1,
|
|
|
|
|
&clnt_sec_ctx);
|
2011-09-29 18:45:21 -04:00
|
|
|
if (status) {
|
2012-02-13 16:08:21 -05:00
|
|
|
print_error("nfs41_GetLUID: SeCreateClientSecurityFromSubjectContext "
|
2011-12-21 15:53:17 -05:00
|
|
|
"failed %x\n", status);
|
2011-09-29 18:45:21 -04:00
|
|
|
goto release_sec_ctx;
|
|
|
|
|
}
|
|
|
|
|
status = SeQueryAuthenticationIdToken(clnt_sec_ctx.ClientToken, id);
|
|
|
|
|
if (status) {
|
2012-02-13 16:08:21 -05:00
|
|
|
print_error("SeQueryAuthenticationIdToken failed %x\n", status);
|
2011-09-29 18:45:21 -04:00
|
|
|
goto release_clnt_sec_ctx;
|
|
|
|
|
}
|
|
|
|
|
release_clnt_sec_ctx:
|
|
|
|
|
SeDeleteClientSecurity(&clnt_sec_ctx);
|
|
|
|
|
release_sec_ctx:
|
|
|
|
|
SeReleaseSubjectContext(&sec_ctx);
|
|
|
|
|
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-06 17:19:46 -05:00
|
|
|
NTSTATUS nfs41_get_sec_ctx(
|
2011-12-21 15:53:17 -05:00
|
|
|
IN enum _SECURITY_IMPERSONATION_LEVEL level,
|
2011-12-06 17:19:46 -05:00
|
|
|
OUT PSECURITY_CLIENT_CONTEXT out_ctx)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status;
|
|
|
|
|
SECURITY_SUBJECT_CONTEXT ctx;
|
|
|
|
|
SECURITY_QUALITY_OF_SERVICE sec_qos;
|
2011-12-21 15:53:17 -05:00
|
|
|
|
2011-12-06 17:19:46 -05:00
|
|
|
SeCaptureSubjectContext(&ctx);
|
|
|
|
|
sec_qos.ContextTrackingMode = SECURITY_STATIC_TRACKING;
|
|
|
|
|
sec_qos.ImpersonationLevel = level;
|
|
|
|
|
sec_qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
|
|
|
|
|
sec_qos.EffectiveOnly = 0;
|
|
|
|
|
status = SeCreateClientSecurityFromSubjectContext(&ctx, &sec_qos, 1, out_ctx);
|
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
|
|
|
print_error("SeCreateClientSecurityFromSubjectContext "
|
|
|
|
|
"failed with %x\n", status);
|
|
|
|
|
}
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2011-12-06 17:19:46 -05:00
|
|
|
DbgP("Created client security token %p\n", out_ctx->ClientToken);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-12-06 17:19:46 -05:00
|
|
|
SeReleaseSubjectContext(&ctx);
|
|
|
|
|
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
NTSTATUS nfs41_CreateVNetRoot(
|
|
|
|
|
IN OUT PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext)
|
|
|
|
|
{
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
2010-10-12 09:46:07 -04:00
|
|
|
NFS41_MOUNT_CONFIG Config;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PMRX_V_NET_ROOT pVNetRoot = (PMRX_V_NET_ROOT)
|
|
|
|
|
pCreateNetRootContext->pVNetRoot;
|
|
|
|
|
__notnull PMRX_NET_ROOT pNetRoot = pVNetRoot->pNetRoot;
|
|
|
|
|
__notnull PMRX_SRV_CALL pSrvCall = pNetRoot->pSrvCall;
|
|
|
|
|
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
|
2010-10-11 14:59:26 -04:00
|
|
|
NFS41GetVNetRootExtension(pVNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
|
2010-10-11 14:59:26 -04:00
|
|
|
NFS41GetNetRootExtension(pNetRoot);
|
2010-11-05 20:08:55 -04:00
|
|
|
NFS41GetDeviceExtension(pCreateNetRootContext->RxContext,DevExt);
|
|
|
|
|
DWORD nfs41d_version = DevExt->nfs41d_version;
|
2011-09-29 18:45:21 -04:00
|
|
|
nfs41_mount_entry *existing_mount = NULL;
|
|
|
|
|
LUID luid;
|
|
|
|
|
BOOLEAN found_existing_mount = FALSE, found_matching_flavor = FALSE;
|
|
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
ASSERT((NodeType(pNetRoot) == RDBSS_NTC_NETROOT) &&
|
|
|
|
|
(NodeType(pNetRoot->pSrvCall) == RDBSS_NTC_SRVCALL));
|
|
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
|
|
|
|
print_srv_call(0, pSrvCall);
|
|
|
|
|
print_net_root(0, pNetRoot);
|
2012-02-13 16:08:21 -05:00
|
|
|
print_v_net_root(0, pVNetRoot);
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2011-04-20 12:36:02 -04:00
|
|
|
DbgP("pVNetRoot=%p pNetRoot=%p pSrvCall=%p\n", pVNetRoot, pNetRoot, pSrvCall);
|
|
|
|
|
DbgP("pNetRoot=%wZ Type=%d pSrvCallName=%wZ VirtualNetRootStatus=0x%x "
|
|
|
|
|
"NetRootStatus=0x%x\n", pNetRoot->pNetRootName,
|
|
|
|
|
pNetRoot->Type, pSrvCall->pSrvCallName,
|
2010-10-11 14:59:26 -04:00
|
|
|
pCreateNetRootContext->VirtualNetRootStatus,
|
|
|
|
|
pCreateNetRootContext->NetRootStatus);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2011-04-20 12:36:02 -04:00
|
|
|
if (pNetRoot->Type != NET_ROOT_DISK && pNetRoot->Type != NET_ROOT_WILD) {
|
2012-02-13 16:08:21 -05:00
|
|
|
print_error("nfs41_CreateVNetRoot: Unsupported NetRoot Type %u\n",
|
|
|
|
|
pNetRoot->Type);
|
2010-10-11 14:59:26 -04:00
|
|
|
status = STATUS_NOT_SUPPORTED;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-18 11:52:31 -05:00
|
|
|
pVNetRootContext->session = INVALID_HANDLE_VALUE;
|
|
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
/* In order to cooperate with other network providers, we must
|
|
|
|
|
* only claim paths of the form '\\server\nfs4\path' */
|
|
|
|
|
status = has_nfs_prefix(pSrvCall->pSrvCallName, pNetRoot->pNetRootName);
|
|
|
|
|
if (status) {
|
2012-02-13 16:08:21 -05:00
|
|
|
print_error("nfs41_CreateVNetRoot: NetRootName %wZ doesn't match "
|
|
|
|
|
"'\\nfs4'!\n", pNetRoot->pNetRootName);
|
2010-10-11 14:59:26 -04:00
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_GOOD;
|
|
|
|
|
pNetRoot->DeviceType = FILE_DEVICE_DISK;
|
|
|
|
|
|
2010-10-12 09:46:07 -04:00
|
|
|
nfs41_MountConfig_InitDefaults(&Config);
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2010-10-12 09:46:34 -04:00
|
|
|
if (pCreateNetRootContext->RxContext->Create.EaLength) {
|
|
|
|
|
/* parse the extended attributes for mount options */
|
2010-10-11 14:59:26 -04:00
|
|
|
status = nfs41_MountConfig_ParseOptions(
|
|
|
|
|
pCreateNetRootContext->RxContext->Create.EaBuffer,
|
|
|
|
|
pCreateNetRootContext->RxContext->Create.EaLength,
|
2010-10-12 09:46:07 -04:00
|
|
|
&Config);
|
2010-10-12 09:45:18 -04:00
|
|
|
if (status != STATUS_SUCCESS)
|
2010-10-11 14:59:26 -04:00
|
|
|
goto out;
|
2011-12-07 18:10:09 -05:00
|
|
|
pVNetRootContext->read_only = Config.ReadOnly;
|
|
|
|
|
pVNetRootContext->write_thru = Config.write_thru;
|
2011-12-08 17:47:34 -05:00
|
|
|
pVNetRootContext->nocache = Config.nocache;
|
2010-10-11 14:59:26 -04:00
|
|
|
} else {
|
2010-10-12 09:46:34 -04:00
|
|
|
/* use the SRV_CALL name (without leading \) as the hostname */
|
|
|
|
|
Config.SrvName.Buffer = pSrvCall->pSrvCallName->Buffer + 1;
|
|
|
|
|
Config.SrvName.Length =
|
|
|
|
|
pSrvCall->pSrvCallName->Length - sizeof(WCHAR);
|
|
|
|
|
Config.SrvName.MaximumLength =
|
|
|
|
|
pSrvCall->pSrvCallName->MaximumLength - sizeof(WCHAR);
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
|
2010-12-01 19:11:47 -05:00
|
|
|
status = map_sec_flavor(&Config.SecFlavor, &pVNetRootContext->sec_flavor);
|
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
|
|
|
DbgP("Invalid rpcsec security flavor %wZ\n", &Config.SecFlavor);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-29 18:45:21 -04:00
|
|
|
status = nfs41_GetLUID(&luid);
|
2011-12-21 15:53:17 -05:00
|
|
|
if (status)
|
2010-12-02 12:28:49 -05:00
|
|
|
goto out;
|
|
|
|
|
|
2011-09-29 18:45:21 -04:00
|
|
|
if (!pNetRootContext->mounts_init) {
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2011-09-29 18:45:21 -04:00
|
|
|
DbgP("Initializing mount array\n");
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-09-29 18:45:21 -04:00
|
|
|
ExInitializeFastMutex(&pNetRootContext->mountLock);
|
2011-12-21 15:53:17 -05:00
|
|
|
pNetRootContext->mounts = RxAllocatePoolWithTag(NonPagedPool,
|
|
|
|
|
sizeof(nfs41_mount_list), NFS41_MM_POOLTAG);
|
2011-09-29 18:45:21 -04:00
|
|
|
if (pNetRootContext->mounts == NULL) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
InitializeListHead(&pNetRootContext->mounts->head);
|
|
|
|
|
pNetRootContext->mounts_init = TRUE;
|
|
|
|
|
} else {
|
|
|
|
|
PLIST_ENTRY pEntry;
|
|
|
|
|
|
|
|
|
|
ExAcquireFastMutex(&pNetRootContext->mountLock);
|
|
|
|
|
pEntry = &pNetRootContext->mounts->head;
|
2011-10-06 12:38:55 -04:00
|
|
|
pEntry = pEntry->Flink;
|
2011-09-29 18:45:21 -04:00
|
|
|
while (pEntry != NULL) {
|
|
|
|
|
existing_mount = (nfs41_mount_entry *)CONTAINING_RECORD(pEntry,
|
|
|
|
|
nfs41_mount_entry, next);
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2011-09-29 18:45:21 -04:00
|
|
|
DbgP("comparing %x.%x with %x.%x\n", luid.HighPart, luid.LowPart,
|
|
|
|
|
existing_mount->login_id.HighPart, existing_mount->login_id.LowPart);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-09-29 18:45:21 -04:00
|
|
|
if (RtlEqualLuid(&luid, &existing_mount->login_id)) {
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2011-09-29 18:45:21 -04:00
|
|
|
DbgP("Found a matching LUID entry\n");
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-09-29 18:45:21 -04:00
|
|
|
found_existing_mount = TRUE;
|
|
|
|
|
switch(pVNetRootContext->sec_flavor) {
|
|
|
|
|
case RPCSEC_AUTH_SYS:
|
|
|
|
|
if (existing_mount->authsys_session != INVALID_HANDLE_VALUE)
|
2011-12-21 15:53:17 -05:00
|
|
|
pVNetRootContext->session =
|
|
|
|
|
existing_mount->authsys_session;
|
2011-09-29 18:45:21 -04:00
|
|
|
break;
|
|
|
|
|
case RPCSEC_AUTHGSS_KRB5:
|
|
|
|
|
if (existing_mount->gssi_session != INVALID_HANDLE_VALUE)
|
|
|
|
|
pVNetRootContext->session = existing_mount->gss_session;
|
|
|
|
|
break;
|
|
|
|
|
case RPCSEC_AUTHGSS_KRB5I:
|
|
|
|
|
if (existing_mount->gss_session != INVALID_HANDLE_VALUE)
|
|
|
|
|
pVNetRootContext->session = existing_mount->gssi_session;
|
|
|
|
|
break;
|
|
|
|
|
case RPCSEC_AUTHGSS_KRB5P:
|
|
|
|
|
if (existing_mount->gssp_session != INVALID_HANDLE_VALUE)
|
|
|
|
|
pVNetRootContext->session = existing_mount->gssp_session;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (pVNetRootContext->session)
|
|
|
|
|
found_matching_flavor = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-02-13 16:08:21 -05:00
|
|
|
if (pEntry->Flink == &pNetRootContext->mounts->head)
|
2011-09-29 18:45:21 -04:00
|
|
|
break;
|
|
|
|
|
pEntry = pEntry->Flink;
|
|
|
|
|
}
|
2012-02-13 16:08:21 -05:00
|
|
|
ExReleaseFastMutex(&pNetRootContext->mountLock);
|
|
|
|
|
#ifdef DEBUG_MOUNT
|
2011-09-29 18:45:21 -04:00
|
|
|
if (!found_matching_flavor)
|
|
|
|
|
DbgP("Didn't find matching security flavor\n");
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-09-29 18:45:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!found_existing_mount || !found_matching_flavor) {
|
|
|
|
|
/* send the mount upcall */
|
2011-10-11 16:03:59 -04:00
|
|
|
status = nfs41_mount(&Config, pVNetRootContext->sec_flavor,
|
2011-09-29 18:45:21 -04:00
|
|
|
&pVNetRootContext->session, &nfs41d_version);
|
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
|
|
|
if (!found_existing_mount) {
|
|
|
|
|
RxFreePool(pNetRootContext->mounts);
|
|
|
|
|
pNetRootContext->mounts_init = FALSE;
|
|
|
|
|
pVNetRootContext->session = INVALID_HANDLE_VALUE;
|
|
|
|
|
}
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!found_existing_mount) {
|
|
|
|
|
/* create a new mount entry and add it to the list */
|
|
|
|
|
nfs41_mount_entry *entry;
|
|
|
|
|
entry = RxAllocatePoolWithTag(NonPagedPool, sizeof(nfs41_mount_entry),
|
|
|
|
|
NFS41_MM_POOLTAG);
|
|
|
|
|
if (entry == NULL) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
RxFreePool(pNetRootContext->mounts);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
entry->authsys_session = entry->gss_session =
|
|
|
|
|
entry->gssi_session = entry->gssp_session = INVALID_HANDLE_VALUE;
|
|
|
|
|
switch (pVNetRootContext->sec_flavor) {
|
|
|
|
|
case RPCSEC_AUTH_SYS:
|
|
|
|
|
entry->authsys_session = pVNetRootContext->session; break;
|
|
|
|
|
case RPCSEC_AUTHGSS_KRB5:
|
|
|
|
|
entry->gss_session = pVNetRootContext->session; break;
|
|
|
|
|
case RPCSEC_AUTHGSS_KRB5I:
|
|
|
|
|
entry->gssi_session = pVNetRootContext->session; break;
|
|
|
|
|
case RPCSEC_AUTHGSS_KRB5P:
|
|
|
|
|
entry->gssp_session = pVNetRootContext->session; break;
|
|
|
|
|
}
|
|
|
|
|
RtlCopyLuid(&entry->login_id, &luid);
|
|
|
|
|
nfs41_AddEntry(pNetRootContext->mountLock, pNetRootContext->mounts, entry);
|
|
|
|
|
} else if (!found_matching_flavor) {
|
|
|
|
|
ASSERT(existing_mount != NULL);
|
|
|
|
|
/* modify existing mount entry */
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2011-09-29 18:45:21 -04:00
|
|
|
DbgP("Using existing %d flavor session 0x%x\n",
|
|
|
|
|
pVNetRootContext->sec_flavor);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-09-29 18:45:21 -04:00
|
|
|
switch (pVNetRootContext->sec_flavor) {
|
|
|
|
|
case RPCSEC_AUTH_SYS:
|
|
|
|
|
existing_mount->authsys_session = pVNetRootContext->session; break;
|
|
|
|
|
case RPCSEC_AUTHGSS_KRB5:
|
|
|
|
|
existing_mount->gss_session = pVNetRootContext->session; break;
|
|
|
|
|
case RPCSEC_AUTHGSS_KRB5I:
|
|
|
|
|
existing_mount->gssi_session = pVNetRootContext->session; break;
|
|
|
|
|
case RPCSEC_AUTHGSS_KRB5P:
|
|
|
|
|
existing_mount->gssp_session = pVNetRootContext->session; break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-11-05 20:08:55 -04:00
|
|
|
pNetRootContext->nfs41d_version = nfs41d_version;
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-12 09:46:34 -04:00
|
|
|
DbgP("Saving new session 0x%x\n", pVNetRootContext->session);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-12-06 17:19:46 -05:00
|
|
|
#ifdef STORE_MOUNT_SEC_CONTEXT
|
2011-12-21 15:53:17 -05:00
|
|
|
status = nfs41_get_sec_ctx(SecurityImpersonation,
|
|
|
|
|
&pVNetRootContext->mount_sec_ctx);
|
2011-12-06 17:19:46 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
pCreateNetRootContext->VirtualNetRootStatus = status;
|
2011-11-08 14:35:17 -05:00
|
|
|
if (pNetRoot->Context == NULL)
|
|
|
|
|
pCreateNetRootContext->NetRootStatus = status;
|
2010-10-11 14:59:26 -04:00
|
|
|
pCreateNetRootContext->Callback(pCreateNetRootContext);
|
|
|
|
|
|
|
|
|
|
/* RDBSS expects that MRxCreateVNetRoot returns STATUS_PENDING
|
|
|
|
|
* on success or failure */
|
|
|
|
|
status = STATUS_PENDING;
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID nfs41_ExtractNetRootName(
|
|
|
|
|
IN PUNICODE_STRING FilePathName,
|
2011-12-21 15:53:17 -05:00
|
|
|
IN PMRX_SRV_CALL SrvCall,
|
2010-10-11 14:59:26 -04:00
|
|
|
OUT PUNICODE_STRING NetRootName,
|
|
|
|
|
OUT PUNICODE_STRING RestOfName OPTIONAL)
|
|
|
|
|
{
|
|
|
|
|
ULONG length = FilePathName->Length;
|
|
|
|
|
PWCH w = FilePathName->Buffer;
|
|
|
|
|
PWCH wlimit = (PWCH)(((PCHAR)w)+length);
|
|
|
|
|
PWCH wlow;
|
|
|
|
|
|
|
|
|
|
w += (SrvCall->pSrvCallName->Length/sizeof(WCHAR));
|
|
|
|
|
NetRootName->Buffer = wlow = w;
|
|
|
|
|
/* parse the entire path into NetRootName */
|
|
|
|
|
#if USE_ENTIRE_PATH
|
|
|
|
|
w = wlimit;
|
|
|
|
|
#else
|
|
|
|
|
for (;;) {
|
|
|
|
|
if (w >= wlimit)
|
|
|
|
|
break;
|
|
|
|
|
if ((*w == OBJ_NAME_PATH_SEPARATOR) && (w != wlow))
|
|
|
|
|
break;
|
|
|
|
|
w++;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
NetRootName->Length = NetRootName->MaximumLength
|
|
|
|
|
= (USHORT)((PCHAR)w - (PCHAR)wlow);
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
|
|
|
|
DbgP("In: pSrvCall %p PathName=%wZ SrvCallName=%wZ Out: NetRootName=%wZ\n",
|
|
|
|
|
SrvCall, FilePathName, SrvCall->pSrvCallName, NetRootName);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_FinalizeSrvCall(
|
2011-12-21 15:53:17 -05:00
|
|
|
PMRX_SRV_CALL pSrvCall,
|
|
|
|
|
BOOLEAN Force)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
PNFS41_SERVER_ENTRY pServerEntry = (PNFS41_SERVER_ENTRY)(pSrvCall->Context);
|
|
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
print_srv_call(0, pSrvCall);
|
|
|
|
|
|
|
|
|
|
if (pSrvCall->Context == NULL)
|
|
|
|
|
goto out;
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
InterlockedCompareExchangePointer(&pServerEntry->pRdbssSrvCall,
|
|
|
|
|
NULL, pSrvCall);
|
2010-10-11 14:59:26 -04:00
|
|
|
RxFreePool(pServerEntry);
|
|
|
|
|
|
|
|
|
|
pSrvCall->Context = NULL;
|
|
|
|
|
out:
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_FinalizeNetRoot(
|
|
|
|
|
IN OUT PMRX_NET_ROOT pNetRoot,
|
2011-12-21 15:53:17 -05:00
|
|
|
IN PBOOLEAN ForceDisconnect)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
PNFS41_NETROOT_EXTENSION pNetRootContext =
|
|
|
|
|
NFS41GetNetRootExtension((PMRX_NET_ROOT)pNetRoot);
|
|
|
|
|
nfs41_updowncall_entry *tmp;
|
2011-09-29 18:45:21 -04:00
|
|
|
nfs41_mount_entry *mount_tmp;
|
2010-11-05 20:08:55 -04:00
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
|
|
|
|
print_net_root(1, pNetRoot);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2011-04-20 12:36:02 -04:00
|
|
|
if (pNetRoot->Type != NET_ROOT_DISK && pNetRoot->Type != NET_ROOT_WILD) {
|
2010-10-11 14:59:26 -04:00
|
|
|
status = STATUS_NOT_SUPPORTED;
|
|
|
|
|
goto out;
|
2011-04-20 12:36:02 -04:00
|
|
|
}
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2011-09-29 18:45:21 -04:00
|
|
|
if (pNetRootContext == NULL || !pNetRootContext->mounts_init) {
|
2012-02-13 16:08:21 -05:00
|
|
|
print_error("nfs41_FinalizeNetRoot: No valid session established\n");
|
2010-10-11 14:59:26 -04:00
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pNetRoot->NumberOfFcbs > 0 || pNetRoot->NumberOfSrvOpens > 0) {
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("%d open Fcbs %d open SrvOpens\n", pNetRoot->NumberOfFcbs,
|
2010-10-11 14:59:26 -04:00
|
|
|
pNetRoot->NumberOfSrvOpens);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-29 18:45:21 -04:00
|
|
|
do {
|
|
|
|
|
nfs41_GetFirstMountEntry(pNetRootContext->mountLock,
|
|
|
|
|
pNetRootContext->mounts, mount_tmp);
|
|
|
|
|
if (mount_tmp == NULL)
|
|
|
|
|
break;
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2011-12-21 15:53:17 -05:00
|
|
|
DbgP("Removing entry luid %x.%x from mount list\n",
|
|
|
|
|
mount_tmp->login_id.HighPart, mount_tmp->login_id.LowPart);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-09-29 18:45:21 -04:00
|
|
|
if (mount_tmp->authsys_session != INVALID_HANDLE_VALUE) {
|
2011-12-21 15:53:17 -05:00
|
|
|
status = nfs41_unmount(mount_tmp->authsys_session,
|
|
|
|
|
pNetRootContext->nfs41d_version);
|
2011-09-29 18:45:21 -04:00
|
|
|
if (status)
|
|
|
|
|
print_error("nfs41_unmount AUTH_SYS failed with %d\n", status);
|
2010-12-02 12:28:49 -05:00
|
|
|
}
|
2011-09-29 18:45:21 -04:00
|
|
|
if (mount_tmp->gss_session != INVALID_HANDLE_VALUE) {
|
2011-12-21 15:53:17 -05:00
|
|
|
status = nfs41_unmount(mount_tmp->gss_session,
|
|
|
|
|
pNetRootContext->nfs41d_version);
|
2011-09-29 18:45:21 -04:00
|
|
|
if (status)
|
2011-12-21 15:53:17 -05:00
|
|
|
print_error("nfs41_unmount RPCSEC_GSS_KRB5 failed with %d\n",
|
|
|
|
|
status);
|
2010-12-02 12:28:49 -05:00
|
|
|
}
|
2011-09-29 18:45:21 -04:00
|
|
|
if (mount_tmp->gssi_session != INVALID_HANDLE_VALUE) {
|
2011-12-21 15:53:17 -05:00
|
|
|
status = nfs41_unmount(mount_tmp->gssi_session,
|
|
|
|
|
pNetRootContext->nfs41d_version);
|
2011-09-29 18:45:21 -04:00
|
|
|
if (status)
|
2011-12-21 15:53:17 -05:00
|
|
|
print_error("nfs41_unmount RPCSEC_GSS_KRB5I failed with %d\n",
|
|
|
|
|
status);
|
2011-09-29 18:45:21 -04:00
|
|
|
}
|
|
|
|
|
if (mount_tmp->gssp_session != INVALID_HANDLE_VALUE) {
|
2011-12-21 15:53:17 -05:00
|
|
|
status = nfs41_unmount(mount_tmp->gssp_session,
|
|
|
|
|
pNetRootContext->nfs41d_version);
|
2011-09-29 18:45:21 -04:00
|
|
|
if (status)
|
2011-12-21 15:53:17 -05:00
|
|
|
print_error("nfs41_unmount RPCSEC_GSS_KRB5P failed with %d\n",
|
|
|
|
|
status);
|
2011-09-29 18:45:21 -04:00
|
|
|
}
|
2011-12-21 15:53:17 -05:00
|
|
|
nfs41_RemoveEntry(pNetRootContext->mountLock, pNetRootContext->mounts,
|
|
|
|
|
mount_tmp);
|
2011-09-29 18:45:21 -04:00
|
|
|
RxFreePool(mount_tmp);
|
|
|
|
|
} while (1);
|
|
|
|
|
/* ignore any errors from unmount */
|
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
|
RxFreePool(pNetRootContext->mounts);
|
|
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
// check if there is anything waiting in the upcall or downcall queue
|
|
|
|
|
do {
|
|
|
|
|
nfs41_GetFirstEntry(upcallLock, upcall, tmp);
|
|
|
|
|
if (tmp != NULL) {
|
|
|
|
|
DbgP("Removing entry from upcall list\n");
|
|
|
|
|
nfs41_RemoveEntry(upcallLock, upcall, tmp);
|
|
|
|
|
tmp->status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
KeSetEvent(&tmp->cond, 0, FALSE);
|
|
|
|
|
} else
|
|
|
|
|
break;
|
|
|
|
|
} while (1);
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
nfs41_GetFirstEntry(downcallLock, downcall, tmp);
|
|
|
|
|
if (tmp != NULL) {
|
|
|
|
|
DbgP("Removing entry from downcall list\n");
|
|
|
|
|
nfs41_RemoveEntry(downcallLock, downcall, tmp);
|
|
|
|
|
tmp->status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
KeSetEvent(&tmp->cond, 0, FALSE);
|
|
|
|
|
} else
|
|
|
|
|
break;
|
|
|
|
|
} while (1);
|
|
|
|
|
out:
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_FinalizeVNetRoot(
|
|
|
|
|
IN OUT PMRX_V_NET_ROOT pVNetRoot,
|
2011-12-21 15:53:17 -05:00
|
|
|
IN PBOOLEAN ForceDisconnect)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
2011-12-06 17:19:46 -05:00
|
|
|
PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
|
|
|
|
|
NFS41GetVNetRootExtension(pVNetRoot);
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
|
|
|
|
print_v_net_root(1, pVNetRoot);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-04-20 12:36:02 -04:00
|
|
|
if (pVNetRoot->pNetRoot->Type != NET_ROOT_DISK &&
|
|
|
|
|
pVNetRoot->pNetRoot->Type != NET_ROOT_WILD)
|
2010-10-11 14:59:26 -04:00
|
|
|
status = STATUS_NOT_SUPPORTED;
|
2011-12-06 17:19:46 -05:00
|
|
|
#ifdef STORE_MOUNT_SEC_CONTEXT
|
2012-01-18 11:52:31 -05:00
|
|
|
else if (pVNetRootContext->session != INVALID_HANDLE_VALUE) {
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
|
|
|
|
DbgP("nfs41_FinalizeVNetRoot: deleting security context: %p\n",
|
|
|
|
|
pVNetRootContext->mount_sec_ctx.ClientToken);
|
|
|
|
|
#endif
|
2011-12-20 15:19:01 -05:00
|
|
|
SeDeleteClientSecurity(&pVNetRootContext->mount_sec_ctx);
|
2012-01-18 11:52:31 -05:00
|
|
|
}
|
2011-12-06 17:19:46 -05:00
|
|
|
#endif
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_MOUNT
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
BOOLEAN isDataAccess(
|
|
|
|
|
ACCESS_MASK mask)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
2012-02-13 16:08:21 -05:00
|
|
|
if (mask & (FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA))
|
2010-10-11 14:59:26 -04:00
|
|
|
return TRUE;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS map_open_errors(
|
|
|
|
|
DWORD status,
|
|
|
|
|
USHORT len)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
switch (status) {
|
|
|
|
|
case NO_ERROR: return STATUS_SUCCESS;
|
|
|
|
|
case ERROR_ACCESS_DENIED:
|
|
|
|
|
if (len > 0) return STATUS_NETWORK_ACCESS_DENIED;
|
|
|
|
|
else return STATUS_SUCCESS;
|
|
|
|
|
case ERROR_INVALID_NAME: return STATUS_OBJECT_NAME_INVALID;
|
|
|
|
|
case ERROR_FILE_EXISTS: return STATUS_OBJECT_NAME_COLLISION;
|
|
|
|
|
case ERROR_FILE_INVALID: return STATUS_FILE_INVALID;
|
|
|
|
|
case ERROR_FILE_NOT_FOUND: return STATUS_OBJECT_NAME_NOT_FOUND;
|
|
|
|
|
case ERROR_FILENAME_EXCED_RANGE: return STATUS_NAME_TOO_LONG;
|
|
|
|
|
case ERROR_NETWORK_ACCESS_DENIED: return STATUS_NETWORK_ACCESS_DENIED;
|
|
|
|
|
case ERROR_PATH_NOT_FOUND: return STATUS_OBJECT_PATH_NOT_FOUND;
|
2010-11-05 14:18:00 -04:00
|
|
|
case ERROR_BAD_NETPATH: return STATUS_BAD_NETWORK_PATH;
|
2010-10-11 14:59:26 -04:00
|
|
|
case ERROR_SHARING_VIOLATION: return STATUS_SHARING_VIOLATION;
|
2010-10-12 10:00:57 -04:00
|
|
|
case ERROR_REPARSE: return STATUS_REPARSE;
|
2010-10-15 17:53:47 -04:00
|
|
|
case ERROR_TOO_MANY_LINKS: return STATUS_TOO_MANY_LINKS;
|
2010-10-11 14:59:26 -04:00
|
|
|
default:
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("[ERROR] nfs41_Create: upcall returned %d returning "
|
2010-10-11 14:59:26 -04:00
|
|
|
"STATUS_INSUFFICIENT_RESOURCES\n", status);
|
|
|
|
|
case ERROR_OUTOFMEMORY: return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-12-21 15:53:17 -05:00
|
|
|
|
|
|
|
|
DWORD map_disposition_to_create_retval(
|
|
|
|
|
DWORD disposition,
|
|
|
|
|
DWORD errno)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
switch(disposition) {
|
|
|
|
|
case FILE_SUPERSEDE:
|
|
|
|
|
if (errno == ERROR_FILE_NOT_FOUND) return FILE_CREATED;
|
|
|
|
|
else return FILE_SUPERSEDED;
|
|
|
|
|
case FILE_CREATE: return FILE_CREATED;
|
|
|
|
|
case FILE_OPEN: return FILE_OPENED;
|
|
|
|
|
case FILE_OPEN_IF:
|
|
|
|
|
if (errno == ERROR_FILE_NOT_FOUND) return FILE_CREATED;
|
|
|
|
|
else return FILE_OPENED;
|
|
|
|
|
case FILE_OVERWRITE: return FILE_OVERWRITTEN;
|
|
|
|
|
case FILE_OVERWRITE_IF:
|
|
|
|
|
if (errno == ERROR_FILE_NOT_FOUND) return FILE_CREATED;
|
|
|
|
|
else return FILE_OVERWRITTEN;
|
|
|
|
|
default:
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("unknown disposition %d\n", disposition);
|
2010-10-11 14:59:26 -04:00
|
|
|
return FILE_OPENED;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_Create(
|
|
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
|
2011-12-21 15:53:17 -05:00
|
|
|
nfs41_updowncall_entry *entry = NULL;
|
2010-10-11 14:59:26 -04:00
|
|
|
FCB_INIT_PACKET InitPacket;
|
|
|
|
|
RX_FILE_TYPE StorageType = 0;
|
|
|
|
|
NT_CREATE_PARAMETERS params = RxContext->Create.NtCreateParameters;
|
|
|
|
|
PFILE_FULL_EA_INFORMATION eainfo = NULL;
|
|
|
|
|
nfs3_attrs *attrs = NULL;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
|
|
|
|
|
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
|
|
|
|
|
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
|
|
|
|
|
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
|
2010-10-11 14:59:26 -04:00
|
|
|
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PMRX_FCB Fcb = RxContext->pFcb;
|
|
|
|
|
__notnull PNFS41_FCB nfs41_fcb = (PNFS41_FCB)Fcb->Context;
|
|
|
|
|
PNFS41_FOBX nfs41_fobx = NULL;
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
LARGE_INTEGER t1, t2;
|
|
|
|
|
t1 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
|
|
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_OPEN
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
2011-12-21 15:53:17 -05:00
|
|
|
print_debug_header(RxContext);
|
|
|
|
|
print_nt_create_params(1, RxContext->Create.NtCreateParameters);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (RxContext->CurrentIrp->AssociatedIrp.SystemBuffer)
|
2012-02-13 16:08:21 -05:00
|
|
|
print_ea_info(0, RxContext->CurrentIrp->AssociatedIrp.SystemBuffer);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2011-04-20 12:36:02 -04:00
|
|
|
if (Fcb->pNetRoot->Type != NET_ROOT_DISK &&
|
|
|
|
|
Fcb->pNetRoot->Type != NET_ROOT_WILD) {
|
2012-02-13 16:08:21 -05:00
|
|
|
print_error("nfs41_Create: Unsupported NetRoot Type %u\n",
|
|
|
|
|
Fcb->pNetRoot->Type);
|
2011-04-20 12:36:02 -04:00
|
|
|
status = STATUS_NOT_SUPPORTED;
|
2010-10-11 14:59:26 -04:00
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (FlagOn(Fcb->FcbState, FCB_STATE_PAGING_FILE )) {
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("FCB_STATE_PAGING_FILE not implemented\n");
|
2010-10-11 14:59:26 -04:00
|
|
|
status = STATUS_NOT_IMPLEMENTED;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-29 18:45:21 -04:00
|
|
|
if (!pNetRootContext->mounts_init) {
|
2012-02-13 16:08:21 -05:00
|
|
|
print_error("nfs41_Create: No valid session established\n");
|
2010-10-11 14:59:26 -04:00
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-04 10:57:06 -04:00
|
|
|
if (pVNetRootContext->read_only &&
|
|
|
|
|
((params.DesiredAccess & FILE_WRITE_DATA) ||
|
|
|
|
|
(params.DesiredAccess & FILE_APPEND_DATA))) {
|
|
|
|
|
DbgP("Read-only mount\n");
|
|
|
|
|
status = STATUS_ACCESS_DENIED;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-06 17:19:46 -05:00
|
|
|
#if defined(STORE_MOUNT_SEC_CONTEXT) && defined (USE_MOUNT_SEC_CONTEXT)
|
|
|
|
|
status = nfs41_UpcallCreate(NFS41_OPEN, &pVNetRootContext->mount_sec_ctx,
|
|
|
|
|
#else
|
|
|
|
|
status = nfs41_UpcallCreate(NFS41_OPEN, NULL,
|
|
|
|
|
#endif
|
|
|
|
|
pVNetRootContext->session, INVALID_HANDLE_VALUE,
|
2012-02-13 16:08:21 -05:00
|
|
|
pNetRootContext->nfs41d_version,
|
|
|
|
|
SrvOpen->pAlreadyPrefixedName, &entry);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (status)
|
|
|
|
|
goto out;
|
|
|
|
|
entry->u.Open.filename = SrvOpen->pAlreadyPrefixedName;
|
|
|
|
|
entry->u.Open.access_mask = params.DesiredAccess;
|
|
|
|
|
entry->u.Open.access_mode = params.ShareAccess;
|
|
|
|
|
entry->u.Open.attrs = params.FileAttributes;
|
|
|
|
|
entry->u.Open.disp = params.Disposition;
|
|
|
|
|
entry->u.Open.copts = params.CreateOptions;
|
2012-01-19 19:46:03 -05:00
|
|
|
entry->u.Open.srv_open = SrvOpen;
|
2010-10-11 14:59:26 -04:00
|
|
|
if (isDataAccess(params.DesiredAccess))
|
2011-12-21 17:42:04 -05:00
|
|
|
entry->u.Open.open_owner_id = InterlockedIncrement(&open_owner_id);
|
2010-10-11 14:59:26 -04:00
|
|
|
// if we are creating a file check if nfsv3attributes were passed in
|
|
|
|
|
if (params.Disposition != FILE_OPEN && params.Disposition != FILE_OVERWRITE) {
|
|
|
|
|
if (RxContext->CurrentIrp->AssociatedIrp.SystemBuffer) {
|
|
|
|
|
eainfo = (PFILE_FULL_EA_INFORMATION)
|
|
|
|
|
RxContext->CurrentIrp->AssociatedIrp.SystemBuffer;
|
|
|
|
|
if (AnsiStrEq(&NfsV3Attributes, eainfo->EaName, eainfo->EaNameLength)) {
|
|
|
|
|
attrs = (nfs3_attrs *)(eainfo->EaName + eainfo->EaNameLength + 1);
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_OPEN
|
|
|
|
|
DbgP("creating file with mode %o\n", attrs->mode);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
entry->u.Open.mode = attrs->mode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!entry->u.Open.mode)
|
|
|
|
|
entry->u.Open.mode = 0777;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 16:36:39 -05:00
|
|
|
status = nfs41_UpcallWaitForReply(entry);
|
2011-12-06 17:19:46 -05:00
|
|
|
#ifndef USE_MOUNT_SEC_CONTEXT
|
2011-01-07 14:49:41 -05:00
|
|
|
SeDeleteClientSecurity(&entry->sec_ctx);
|
2011-12-06 17:19:46 -05:00
|
|
|
#endif
|
2011-12-21 16:36:39 -05:00
|
|
|
if (status != STATUS_SUCCESS) {
|
|
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2010-10-12 10:06:45 -04:00
|
|
|
if (entry->status == NO_ERROR && entry->errno == ERROR_REPARSE) {
|
2010-10-12 10:01:40 -04:00
|
|
|
/* symbolic link handling. when attempting to open a symlink when the
|
|
|
|
|
* FILE_OPEN_REPARSE_POINT flag is not set, replace the filename with
|
|
|
|
|
* the symlink target's by calling RxPrepareToReparseSymbolicLink()
|
|
|
|
|
* and returning STATUS_REPARSE. the object manager will attempt to
|
|
|
|
|
* open the new path, and return its handle for the original open */
|
2010-09-29 13:12:56 -04:00
|
|
|
PRDBSS_DEVICE_OBJECT DeviceObject = RxContext->RxDeviceObject;
|
2011-12-21 15:53:17 -05:00
|
|
|
PV_NET_ROOT VNetRoot = (PV_NET_ROOT)
|
|
|
|
|
RxContext->pRelevantSrvOpen->pVNetRoot;
|
2010-09-29 13:12:56 -04:00
|
|
|
PUNICODE_STRING VNetRootPrefix = &VNetRoot->PrefixEntry.Prefix;
|
2010-10-12 10:01:40 -04:00
|
|
|
UNICODE_STRING AbsPath;
|
|
|
|
|
PCHAR buf;
|
|
|
|
|
BOOLEAN ReparseRequired;
|
|
|
|
|
|
|
|
|
|
/* allocate the string for RxPrepareToReparseSymbolicLink(), and
|
2010-09-29 13:12:56 -04:00
|
|
|
* format an absolute path "DeviceName+VNetRootName+symlink" */
|
2010-10-11 09:58:52 -04:00
|
|
|
AbsPath.Length = DeviceObject->DeviceName.Length +
|
2010-09-29 13:12:56 -04:00
|
|
|
VNetRootPrefix->Length + entry->u.Open.symlink.Length;
|
2010-10-11 09:58:52 -04:00
|
|
|
AbsPath.MaximumLength = AbsPath.Length + sizeof(UNICODE_NULL);
|
2010-10-12 10:01:40 -04:00
|
|
|
AbsPath.Buffer = RxAllocatePoolWithTag(NonPagedPool,
|
|
|
|
|
AbsPath.MaximumLength, NFS41_MM_POOLTAG);
|
|
|
|
|
if (AbsPath.Buffer == NULL) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out_free;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buf = (PCHAR)AbsPath.Buffer;
|
2011-12-21 15:53:17 -05:00
|
|
|
RtlCopyMemory(buf, DeviceObject->DeviceName.Buffer,
|
|
|
|
|
DeviceObject->DeviceName.Length);
|
2010-10-12 10:01:40 -04:00
|
|
|
buf += DeviceObject->DeviceName.Length;
|
2010-09-29 13:12:56 -04:00
|
|
|
RtlCopyMemory(buf, VNetRootPrefix->Buffer, VNetRootPrefix->Length);
|
|
|
|
|
buf += VNetRootPrefix->Length;
|
2011-12-21 15:53:17 -05:00
|
|
|
RtlCopyMemory(buf, entry->u.Open.symlink.Buffer,
|
|
|
|
|
entry->u.Open.symlink.Length);
|
2010-10-15 12:06:16 -04:00
|
|
|
RxFreePool(entry->u.Open.symlink.Buffer);
|
2010-10-11 09:58:52 -04:00
|
|
|
buf += entry->u.Open.symlink.Length;
|
|
|
|
|
*(PWCHAR)buf = UNICODE_NULL;
|
2010-10-12 10:01:40 -04:00
|
|
|
|
|
|
|
|
status = RxPrepareToReparseSymbolicLink(RxContext,
|
2010-09-29 13:11:27 -04:00
|
|
|
entry->u.Open.symlink_embedded, &AbsPath, TRUE, &ReparseRequired);
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_OPEN
|
2010-09-29 13:11:27 -04:00
|
|
|
DbgP("RxPrepareToReparseSymbolicLink(%u, '%wZ') returned %08lX, "
|
|
|
|
|
"FileName is '%wZ'\n", entry->u.Open.symlink_embedded,
|
2010-10-12 10:01:40 -04:00
|
|
|
&AbsPath, status, &RxContext->CurrentIrpSp->FileObject->FileName);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-12 10:01:40 -04:00
|
|
|
if (status == STATUS_SUCCESS)
|
|
|
|
|
status = ReparseRequired ? STATUS_REPARSE :
|
|
|
|
|
STATUS_OBJECT_PATH_NOT_FOUND;
|
|
|
|
|
goto out_free;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
status = map_open_errors(entry->status,
|
|
|
|
|
SrvOpen->pAlreadyPrefixedName->Length);
|
|
|
|
|
if (status) {
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_OPEN
|
2010-11-30 13:02:32 -05:00
|
|
|
print_open_error(1, status);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
goto out_free;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!RxIsFcbAcquiredExclusive(Fcb)) {
|
|
|
|
|
ASSERT(!RxIsFcbAcquiredShared(Fcb));
|
|
|
|
|
RxAcquireExclusiveFcbResourceInMRx(Fcb);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RxContext->pFobx = RxCreateNetFobx(RxContext, SrvOpen);
|
2011-12-21 15:53:17 -05:00
|
|
|
if (RxContext->pFobx == NULL) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
2010-10-11 14:59:26 -04:00
|
|
|
goto out_free;
|
2011-01-07 14:49:41 -05:00
|
|
|
}
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_OPEN
|
|
|
|
|
DbgP("nfs41_Create: created FOBX %p\n", RxContext->pFobx);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
nfs41_fobx = (PNFS41_FOBX)(RxContext->pFobx)->Context;
|
2011-04-13 15:28:48 -04:00
|
|
|
nfs41_fobx->nfs41_open_state = entry->open_state;
|
2011-12-06 17:19:46 -05:00
|
|
|
#ifndef USE_MOUNT_SEC_CONTEXT
|
|
|
|
|
status = nfs41_get_sec_ctx(SecurityImpersonation, &nfs41_fobx->sec_ctx);
|
|
|
|
|
if (status)
|
|
|
|
|
goto out_free;
|
|
|
|
|
#else
|
|
|
|
|
RtlCopyMemory(&nfs41_fobx->sec_ctx, &pVNetRootContext->mount_sec_ctx,
|
|
|
|
|
sizeof(nfs41_fobx->sec_ctx));
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
// we get attributes only for data access and file (not directories)
|
2012-02-08 18:24:19 -05:00
|
|
|
if (Fcb->OpenCount == 0 ||
|
|
|
|
|
(Fcb->OpenCount > 0 &&
|
|
|
|
|
nfs41_fcb->changeattr != entry->u.Open.changeattr)) {
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_OPEN
|
2010-10-11 14:59:26 -04:00
|
|
|
print_basic_info(1, &entry->u.Open.binfo);
|
|
|
|
|
print_std_info(1, &entry->u.Open.sinfo);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
RtlCopyMemory(&nfs41_fcb->BasicInfo, &entry->u.Open.binfo,
|
|
|
|
|
sizeof(entry->u.Open.binfo));
|
|
|
|
|
RtlCopyMemory(&nfs41_fcb->StandardInfo, &entry->u.Open.sinfo,
|
|
|
|
|
sizeof(entry->u.Open.sinfo));
|
|
|
|
|
nfs41_fcb->mode = entry->u.Open.mode;
|
|
|
|
|
nfs41_fcb->changeattr = entry->u.Open.changeattr;
|
|
|
|
|
nfs41_fcb->Flags = FCB_BASIC_INFO_CACHED | FCB_STANDARD_INFO_CACHED;
|
|
|
|
|
|
|
|
|
|
RxFormInitPacket(InitPacket,
|
|
|
|
|
&entry->u.Open.binfo.FileAttributes,
|
|
|
|
|
&entry->u.Open.sinfo.NumberOfLinks,
|
|
|
|
|
&entry->u.Open.binfo.CreationTime,
|
|
|
|
|
&entry->u.Open.binfo.LastAccessTime,
|
|
|
|
|
&entry->u.Open.binfo.LastWriteTime,
|
|
|
|
|
&entry->u.Open.binfo.ChangeTime,
|
|
|
|
|
&entry->u.Open.sinfo.AllocationSize,
|
|
|
|
|
&entry->u.Open.sinfo.EndOfFile,
|
|
|
|
|
&entry->u.Open.sinfo.EndOfFile);
|
|
|
|
|
|
|
|
|
|
if (entry->u.Open.sinfo.Directory)
|
|
|
|
|
StorageType = FileTypeDirectory;
|
|
|
|
|
else
|
|
|
|
|
StorageType = FileTypeFile;
|
|
|
|
|
|
|
|
|
|
RxFinishFcbInitialization(Fcb, RDBSS_STORAGE_NTC(StorageType),
|
|
|
|
|
&InitPacket);
|
|
|
|
|
}
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_OPEN
|
2010-10-11 14:59:26 -04:00
|
|
|
else {
|
|
|
|
|
DbgP("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");
|
|
|
|
|
if (nfs41_fcb->Flags) {
|
|
|
|
|
print_basic_info(1, &nfs41_fcb->BasicInfo);
|
|
|
|
|
print_std_info(1, &nfs41_fcb->StandardInfo);
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2012-02-08 18:24:19 -05:00
|
|
|
if (Fcb->OpenCount > 0 &&
|
|
|
|
|
nfs41_fcb->changeattr != entry->u.Open.changeattr &&
|
|
|
|
|
!nfs41_fcb->StandardInfo.Directory) {
|
2010-10-11 14:59:26 -04:00
|
|
|
ULONG flag = DISABLE_CACHING;
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_OPEN
|
2012-02-08 18:24:19 -05:00
|
|
|
DbgP("nfs41_Create: reopening (changed) file %wZ\n", SrvOpen->pAlreadyPrefixedName);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2012-02-08 18:24:19 -05:00
|
|
|
RxChangeBufferingState((PSRV_OPEN)SrvOpen, ULongToPtr(flag), 1);
|
2012-02-13 16:08:21 -05:00
|
|
|
} else if (!nfs41_fcb->StandardInfo.Directory &&
|
|
|
|
|
isDataAccess(params.DesiredAccess)) {
|
2012-02-08 18:24:19 -05:00
|
|
|
nfs41_fobx->deleg_type = entry->u.Open.deleg_type;
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_OPEN
|
2012-02-08 18:24:19 -05:00
|
|
|
DbgP("nfs41_Create: received delegation %d\n", entry->u.Open.deleg_type);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2012-02-08 18:24:19 -05:00
|
|
|
if (!(params.CreateOptions & FILE_WRITE_THROUGH) &&
|
2012-01-20 15:01:11 -05:00
|
|
|
!pVNetRootContext->write_thru &&
|
2012-02-08 18:24:19 -05:00
|
|
|
(entry->u.Open.deleg_type == 2 ||
|
|
|
|
|
(params.DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)))) {
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_OPEN
|
2012-01-20 15:01:11 -05:00
|
|
|
DbgP("nfs41_Create: enabling write buffering\n");
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2012-01-20 15:01:11 -05:00
|
|
|
SrvOpen->BufferingFlags |=
|
|
|
|
|
(FCB_STATE_WRITECACHING_ENABLED |
|
|
|
|
|
FCB_STATE_WRITEBUFFERING_ENABLED);
|
|
|
|
|
}
|
2012-02-08 18:24:19 -05:00
|
|
|
if (entry->u.Open.deleg_type >= 1 ||
|
|
|
|
|
params.DesiredAccess & FILE_READ_DATA) {
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_OPEN
|
2012-01-20 15:01:11 -05:00
|
|
|
DbgP("nfs41_Create: enabling read buffering\n");
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2012-01-20 15:01:11 -05:00
|
|
|
SrvOpen->BufferingFlags |=
|
|
|
|
|
(FCB_STATE_READBUFFERING_ENABLED |
|
|
|
|
|
FCB_STATE_READCACHING_ENABLED);
|
2011-12-08 17:47:34 -05:00
|
|
|
}
|
2012-01-20 15:01:11 -05:00
|
|
|
if (pVNetRootContext->nocache ||
|
|
|
|
|
(params.CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING)) {
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_OPEN
|
2012-01-20 15:01:11 -05:00
|
|
|
DbgP("nfs41_Create: disabling buffering\n");
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2012-01-20 15:01:11 -05:00
|
|
|
SrvOpen->BufferingFlags = FCB_STATE_DISABLE_LOCAL_BUFFERING;
|
2012-02-13 16:08:21 -05:00
|
|
|
} else if (!entry->u.Open.deleg_type) {
|
2012-02-08 18:24:19 -05:00
|
|
|
nfs41_srvopen_list_entry *oentry;
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_OPEN
|
2012-02-08 18:24:19 -05:00
|
|
|
DbgP("nfs41_Create: received no delegations: srv_open=%p "
|
|
|
|
|
"ctime=%llu\n", SrvOpen, entry->u.Open.changeattr);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2012-02-08 18:24:19 -05:00
|
|
|
oentry = RxAllocatePoolWithTag(NonPagedPool,
|
|
|
|
|
sizeof(nfs41_srvopen_list_entry), NFS41_MM_POOLTAG);
|
|
|
|
|
if (oentry == NULL) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
oentry->srv_open = SrvOpen;
|
|
|
|
|
oentry->nfs41_fobx = nfs41_fobx;
|
|
|
|
|
oentry->ChangeTime = entry->u.Open.changeattr;
|
|
|
|
|
oentry->skip = FALSE;
|
|
|
|
|
nfs41_AddEntry(srvopenLock, openlist, oentry);
|
2012-01-20 15:01:11 -05:00
|
|
|
}
|
2011-04-14 19:50:25 -04:00
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
if ((params.CreateOptions & FILE_DELETE_ON_CLOSE) &&
|
2012-02-13 16:08:21 -05:00
|
|
|
!pVNetRootContext->read_only)
|
2010-10-11 14:59:26 -04:00
|
|
|
nfs41_fcb->StandardInfo.DeletePending = TRUE;
|
|
|
|
|
|
|
|
|
|
RxContext->Create.ReturnedCreateInformation =
|
|
|
|
|
map_disposition_to_create_retval(params.Disposition, entry->errno);
|
|
|
|
|
|
|
|
|
|
RxContext->pFobx->OffsetOfNextEaToReturn = 1;
|
|
|
|
|
RxContext->CurrentIrp->IoStatus.Information =
|
|
|
|
|
RxContext->Create.ReturnedCreateInformation;
|
|
|
|
|
status = RxContext->CurrentIrp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
|
|
out_free:
|
|
|
|
|
if (entry)
|
|
|
|
|
RxFreePool(entry);
|
|
|
|
|
out:
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
t2 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
if ((params.DesiredAccess & FILE_READ_DATA) ||
|
|
|
|
|
(params.DesiredAccess & FILE_WRITE_DATA) ||
|
|
|
|
|
(params.DesiredAccess & FILE_APPEND_DATA) ||
|
|
|
|
|
(params.DesiredAccess & FILE_EXECUTE)) {
|
|
|
|
|
InterlockedIncrement(&open.tops);
|
|
|
|
|
InterlockedAdd64(&open.ticks, t2.QuadPart - t1.QuadPart);
|
|
|
|
|
#ifdef ENABLE_INDV_TIMINGS
|
2011-12-21 15:53:17 -05:00
|
|
|
DbgP("nfs41_Create open delta = %d op=%d sum=%d\n",
|
|
|
|
|
t2.QuadPart - t1.QuadPart, open.tops, open.ticks);
|
2011-09-06 18:01:17 -04:00
|
|
|
#endif
|
|
|
|
|
} else {
|
|
|
|
|
InterlockedIncrement(&lookup.tops);
|
|
|
|
|
InterlockedAdd64(&lookup.ticks, t2.QuadPart - t1.QuadPart);
|
|
|
|
|
#ifdef ENABLE_INDV_TIMINGS
|
2011-12-21 15:53:17 -05:00
|
|
|
DbgP("nfs41_Create lookup delta = %d op=%d sum=%d\n",
|
|
|
|
|
t2.QuadPart - t1.QuadPart, lookup.tops, lookup.ticks);
|
2011-09-06 18:01:17 -04:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_OPEN
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_CollapseOpen(
|
|
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_MORE_PROCESSING_REQUIRED;
|
|
|
|
|
DbgEn();
|
|
|
|
|
DbgEx();
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_ShouldTryToCollapseThisOpen(
|
|
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
|
|
|
|
if (RxContext->pRelevantSrvOpen == NULL)
|
2012-02-13 16:08:21 -05:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
|
else return STATUS_MORE_PROCESSING_REQUIRED;
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ULONG nfs41_ExtendForCache(
|
2011-12-21 15:53:17 -05:00
|
|
|
IN OUT PRX_CONTEXT RxContext,
|
|
|
|
|
IN PLARGE_INTEGER pNewFileSize,
|
|
|
|
|
OUT PLARGE_INTEGER pNewAllocationSize)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_FCB nfs41_fcb = NFS41GetFcbExtension(RxContext->pFcb);
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_CACHE
|
|
|
|
|
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
|
|
|
|
print_debug_header(RxContext);
|
|
|
|
|
DbgP("input: byte count 0x%x filesize 0x%x alloc size 0x%x\n",
|
2011-12-21 15:53:17 -05:00
|
|
|
LowIoContext->ParamsFor.ReadWrite.ByteCount, *pNewFileSize,
|
|
|
|
|
*pNewAllocationSize);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
pNewAllocationSize->QuadPart = pNewFileSize->QuadPart + 8192;
|
2011-12-21 15:53:17 -05:00
|
|
|
nfs41_fcb->StandardInfo.AllocationSize.QuadPart =
|
|
|
|
|
pNewAllocationSize->QuadPart;
|
2010-10-11 14:59:26 -04:00
|
|
|
nfs41_fcb->StandardInfo.EndOfFile.QuadPart = pNewFileSize->QuadPart;
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_CACHE
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgP("new filesize 0x%x new allocation size 0x%x\n", *pNewFileSize,
|
|
|
|
|
*pNewAllocationSize);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
|
|
|
|
#ifdef DEBUG_CACHE
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-08 18:24:19 -05:00
|
|
|
VOID nfs41_remove_srvopen_entry(
|
|
|
|
|
PMRX_SRV_OPEN SrvOpen)
|
|
|
|
|
{
|
|
|
|
|
PLIST_ENTRY pEntry;
|
|
|
|
|
nfs41_srvopen_list_entry *cur;
|
|
|
|
|
ExAcquireFastMutex(&srvopenLock);
|
|
|
|
|
|
|
|
|
|
pEntry = openlist->head.Flink;
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_CLOSE
|
2012-02-08 18:24:19 -05:00
|
|
|
DbgP("nfs41_remove_srvopen_entry: Looking for srv_open=%p\n", SrvOpen);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2012-02-08 18:24:19 -05:00
|
|
|
while (!IsListEmpty(&openlist->head)) {
|
|
|
|
|
cur = (nfs41_srvopen_list_entry *)CONTAINING_RECORD(pEntry,
|
|
|
|
|
nfs41_srvopen_list_entry, next);
|
|
|
|
|
if (cur->srv_open == SrvOpen) {
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_CLOSE
|
2012-02-08 18:24:19 -05:00
|
|
|
DbgP("nfs41_remove_srvopen_entry: Found match\n");
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2012-02-08 18:24:19 -05:00
|
|
|
RemoveEntryList(pEntry);
|
|
|
|
|
RxFreePool(cur);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (pEntry->Flink == &openlist->head) {
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_CLOSE
|
2012-02-08 18:24:19 -05:00
|
|
|
DbgP("nfs41_remove_srvopen_entry: reached end of the list\n");
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2012-02-08 18:24:19 -05:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
pEntry = pEntry->Flink;
|
|
|
|
|
}
|
|
|
|
|
ExReleaseFastMutex(&srvopenLock);
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS map_close_errors(
|
|
|
|
|
DWORD status)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
switch (status) {
|
|
|
|
|
case NO_ERROR: return STATUS_SUCCESS;
|
|
|
|
|
case ERROR_NETNAME_DELETED: return STATUS_NETWORK_NAME_DELETED;
|
2010-11-30 13:10:30 -05:00
|
|
|
case ERROR_NOT_EMPTY: return STATUS_DIRECTORY_NOT_EMPTY;
|
|
|
|
|
case ERROR_FILE_INVALID: return STATUS_FILE_INVALID;
|
2010-10-11 14:59:26 -04:00
|
|
|
default:
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("failed to map windows error %d to NTSTATUS; "
|
|
|
|
|
"defaulting to STATUS_INTERNAL_ERROR\n", status);
|
2010-10-11 14:59:26 -04:00
|
|
|
case ERROR_INTERNAL_ERROR: return STATUS_INTERNAL_ERROR;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_CloseSrvOpen(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
nfs41_updowncall_entry *entry;
|
|
|
|
|
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
|
2010-10-11 14:59:26 -04:00
|
|
|
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
|
2010-11-05 20:08:55 -04:00
|
|
|
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_FCB nfs41_fcb = NFS41GetFcbExtension(RxContext->pFcb);
|
|
|
|
|
__notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
LARGE_INTEGER t1, t2;
|
|
|
|
|
t1 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_CLOSE
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
2011-12-21 15:53:17 -05:00
|
|
|
print_debug_header(RxContext);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2012-02-08 18:24:19 -05:00
|
|
|
if (!nfs41_fobx->deleg_type && !nfs41_fcb->StandardInfo.Directory &&
|
|
|
|
|
(SrvOpen->DesiredAccess &
|
|
|
|
|
(FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA))) {
|
|
|
|
|
nfs41_remove_srvopen_entry(SrvOpen);
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-06 17:19:46 -05:00
|
|
|
status = nfs41_UpcallCreate(NFS41_CLOSE, &nfs41_fobx->sec_ctx,
|
2011-04-13 15:28:48 -04:00
|
|
|
pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
|
2012-02-13 16:08:21 -05:00
|
|
|
pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (status)
|
|
|
|
|
goto out;
|
2012-01-19 19:46:03 -05:00
|
|
|
entry->u.Close.srv_open = SrvOpen;
|
2012-02-13 16:08:21 -05:00
|
|
|
entry->u.Close.filename = SrvOpen->pAlreadyPrefixedName;
|
|
|
|
|
if (!RxContext->pFcb->OpenCount ||
|
|
|
|
|
(nfs41_fcb->StandardInfo.DeletePending &&
|
|
|
|
|
nfs41_fcb->StandardInfo.Directory))
|
2010-10-11 14:59:26 -04:00
|
|
|
entry->u.Close.remove = nfs41_fcb->StandardInfo.DeletePending;
|
2012-02-13 16:08:21 -05:00
|
|
|
if (!RxContext->pFcb->OpenCount)
|
2010-10-11 14:59:26 -04:00
|
|
|
entry->u.Close.renamed = nfs41_fcb->Renamed;
|
|
|
|
|
|
2011-12-21 16:36:39 -05:00
|
|
|
status = nfs41_UpcallWaitForReply(entry);
|
|
|
|
|
#ifndef USE_MOUNT_SEC_CONTEXT
|
|
|
|
|
SeDeleteClientSecurity(&nfs41_fobx->sec_ctx);
|
|
|
|
|
#endif
|
|
|
|
|
if (status != STATUS_SUCCESS) {
|
2010-10-11 14:59:26 -04:00
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* map windows ERRORs to NTSTATUS */
|
|
|
|
|
status = map_close_errors(entry->status);
|
|
|
|
|
RxFreePool(entry);
|
|
|
|
|
out:
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
t2 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
InterlockedIncrement(&close.tops);
|
|
|
|
|
InterlockedAdd64(&close.ticks, t2.QuadPart - t1.QuadPart);
|
|
|
|
|
#ifdef ENABLE_INDV_TIMINGS
|
|
|
|
|
DbgP("nfs41_CloseSrvOpen delta = %d op=%d sum=%d\n",
|
|
|
|
|
t2.QuadPart - t1.QuadPart, close.tops, close.ticks);
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_CLOSE
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_Flush(
|
|
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
2012-02-13 16:08:21 -05:00
|
|
|
return STATUS_SUCCESS;
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_DeallocateForFcb(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN OUT PMRX_FCB pFcb)
|
|
|
|
|
{
|
2011-12-21 15:53:17 -05:00
|
|
|
return STATUS_SUCCESS;
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_DeallocateForFobx(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN OUT PMRX_FOBX pFobx)
|
|
|
|
|
{
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(pFobx);
|
2011-08-24 12:23:04 -04:00
|
|
|
if (nfs41_fobx->acl)
|
|
|
|
|
RxFreePool(nfs41_fobx->acl);
|
2011-12-21 15:53:17 -05:00
|
|
|
return STATUS_SUCCESS;
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
void print_debug_filedirquery_header(
|
|
|
|
|
PRX_CONTEXT RxContext)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
print_debug_header(RxContext);
|
|
|
|
|
DbgP("FileName='%wZ', InfoClass = %s\n",
|
|
|
|
|
GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext),
|
|
|
|
|
print_file_information_class(RxContext->Info.FileInformationClass));
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
void print_querydir_args(
|
|
|
|
|
PRX_CONTEXT RxContext)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
print_debug_filedirquery_header(RxContext);
|
|
|
|
|
DbgP("Filter='%wZ', Index=%d, Restart/Single/Specified/Init=%d/%d/%d/%d\n",
|
2011-12-21 15:53:17 -05:00
|
|
|
&RxContext->pFobx->UnicodeQueryTemplate,
|
|
|
|
|
RxContext->QueryDirectory.FileIndex,
|
2010-10-11 14:59:26 -04:00
|
|
|
RxContext->QueryDirectory.RestartScan,
|
|
|
|
|
RxContext->QueryDirectory.ReturnSingleEntry,
|
|
|
|
|
RxContext->QueryDirectory.IndexSpecified,
|
|
|
|
|
RxContext->QueryDirectory.InitialQuery);
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS map_querydir_errors(
|
|
|
|
|
DWORD status)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
switch (status) {
|
|
|
|
|
case ERROR_ACCESS_DENIED: return STATUS_ACCESS_DENIED;
|
|
|
|
|
case ERROR_BUFFER_OVERFLOW: return STATUS_BUFFER_OVERFLOW;
|
|
|
|
|
case ERROR_FILE_NOT_FOUND: return STATUS_NO_SUCH_FILE;
|
|
|
|
|
case ERROR_NETNAME_DELETED: return STATUS_NETWORK_NAME_DELETED;
|
|
|
|
|
case ERROR_INVALID_PARAMETER: return STATUS_INVALID_PARAMETER;
|
|
|
|
|
case ERROR_NO_MORE_FILES: return STATUS_NO_MORE_FILES;
|
|
|
|
|
case ERROR_OUTOFMEMORY: return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
default:
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("failed to map windows error %d to NTSTATUS; "
|
|
|
|
|
"defaulting to STATUS_INVALID_NETWORK_RESPONSE\n", status);
|
2010-10-11 14:59:26 -04:00
|
|
|
case ERROR_BAD_NET_RESP: return STATUS_INVALID_NETWORK_RESPONSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_QueryDirectory(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_INVALID_PARAMETER;
|
|
|
|
|
nfs41_updowncall_entry *entry;
|
|
|
|
|
FILE_INFORMATION_CLASS InfoClass = RxContext->Info.FileInformationClass;
|
|
|
|
|
PUNICODE_STRING Filter = &RxContext->pFobx->UnicodeQueryTemplate;
|
|
|
|
|
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
|
2010-10-11 14:59:26 -04:00
|
|
|
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
|
2010-11-05 20:08:55 -04:00
|
|
|
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
LARGE_INTEGER t1, t2;
|
|
|
|
|
t1 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_DIR_QUERY
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
|
|
|
|
print_querydir_args(RxContext);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
switch (InfoClass) {
|
2011-12-21 15:53:17 -05:00
|
|
|
/* classes handled in readdir_copy_entry() and readdir_size_for_entry() */
|
2010-10-11 14:59:26 -04:00
|
|
|
case FileNamesInformation:
|
|
|
|
|
case FileDirectoryInformation:
|
|
|
|
|
case FileFullDirectoryInformation:
|
|
|
|
|
case FileIdFullDirectoryInformation:
|
|
|
|
|
case FileBothDirectoryInformation:
|
|
|
|
|
case FileIdBothDirectoryInformation:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2012-02-13 16:08:21 -05:00
|
|
|
print_error("nfs41_QueryDirectory: unhandled dir query class %d\n",
|
|
|
|
|
InfoClass);
|
2010-10-11 14:59:26 -04:00
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2011-12-06 17:19:46 -05:00
|
|
|
status = nfs41_UpcallCreate(NFS41_DIR_QUERY, &nfs41_fobx->sec_ctx,
|
2011-04-13 15:28:48 -04:00
|
|
|
pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
|
2012-02-13 16:08:21 -05:00
|
|
|
pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (status)
|
|
|
|
|
goto out;
|
|
|
|
|
entry->u.QueryFile.InfoClass = InfoClass;
|
|
|
|
|
entry->u.QueryFile.buf_len = RxContext->Info.LengthRemaining;
|
|
|
|
|
entry->u.QueryFile.buf = RxContext->Info.Buffer;
|
2011-09-27 12:21:26 -04:00
|
|
|
entry->u.QueryFile.mdl = IoAllocateMdl(RxContext->Info.Buffer,
|
|
|
|
|
RxContext->Info.LengthRemaining, FALSE, FALSE, NULL);
|
|
|
|
|
if (entry->u.QueryFile.mdl == NULL) {
|
|
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
RxFreePool(entry);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2011-10-06 12:32:50 -04:00
|
|
|
entry->u.QueryFile.mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;
|
|
|
|
|
MmProbeAndLockPages(entry->u.QueryFile.mdl, KernelMode, IoModifyAccess);
|
2011-09-27 12:21:26 -04:00
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
entry->u.QueryFile.filter = Filter;
|
|
|
|
|
entry->u.QueryFile.initial_query = RxContext->QueryDirectory.InitialQuery;
|
|
|
|
|
entry->u.QueryFile.restart_scan = RxContext->QueryDirectory.RestartScan;
|
|
|
|
|
entry->u.QueryFile.return_single = RxContext->QueryDirectory.ReturnSingleEntry;
|
|
|
|
|
|
|
|
|
|
if (nfs41_UpcallWaitForReply(entry) != STATUS_SUCCESS) {
|
|
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2011-10-06 12:32:50 -04:00
|
|
|
MmUnlockPages(entry->u.QueryFile.mdl);
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
if (entry->status == STATUS_BUFFER_TOO_SMALL) {
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("nfs41_QueryDirectory: buffer too small provided %d need %d\n",
|
2010-10-11 14:59:26 -04:00
|
|
|
RxContext->Info.LengthRemaining, entry->u.QueryFile.buf_len);
|
|
|
|
|
RxContext->InformationToReturn = entry->u.QueryFile.buf_len;
|
|
|
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
|
} else if (entry->status == STATUS_SUCCESS) {
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
InterlockedIncrement(&readdir.sops);
|
|
|
|
|
InterlockedAdd64(&readdir.size, entry->u.QueryFile.buf_len);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
RxContext->Info.LengthRemaining -= entry->u.QueryFile.buf_len;
|
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
|
} else {
|
|
|
|
|
/* map windows ERRORs to NTSTATUS */
|
|
|
|
|
status = map_querydir_errors(entry->status);
|
|
|
|
|
}
|
2011-09-27 12:21:26 -04:00
|
|
|
IoFreeMdl(entry->u.QueryFile.mdl);
|
2010-10-11 14:59:26 -04:00
|
|
|
RxFreePool(entry);
|
|
|
|
|
out:
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
t2 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
InterlockedIncrement(&readdir.tops);
|
|
|
|
|
InterlockedAdd64(&readdir.ticks, t2.QuadPart - t1.QuadPart);
|
|
|
|
|
#ifdef ENABLE_INDV_TIMINGS
|
|
|
|
|
DbgP("nfs41_QueryDirectory delta = %d ops=%d sum=%d\n",
|
|
|
|
|
t2.QuadPart - t1.QuadPart, readdir.tops, readdir.ticks);
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_DIR_QUERY
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
void print_queryvolume_args(
|
|
|
|
|
PRX_CONTEXT RxContext)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
print_debug_header(RxContext);
|
|
|
|
|
DbgP("FileName='%wZ', InfoClass = %s BufferLen = %d\n",
|
|
|
|
|
GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext),
|
|
|
|
|
print_fs_information_class(RxContext->Info.FileInformationClass),
|
|
|
|
|
RxContext->Info.LengthRemaining);
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS map_volume_errors(
|
|
|
|
|
DWORD status)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
switch (status) {
|
|
|
|
|
case ERROR_ACCESS_DENIED: return STATUS_ACCESS_DENIED;
|
|
|
|
|
case ERROR_VC_DISCONNECTED: return STATUS_CONNECTION_DISCONNECTED;
|
|
|
|
|
case ERROR_NETNAME_DELETED: return STATUS_NETWORK_NAME_DELETED;
|
|
|
|
|
case ERROR_INVALID_PARAMETER: return STATUS_INVALID_PARAMETER;
|
|
|
|
|
case ERROR_OUTOFMEMORY: return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
default:
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("failed to map windows error %d to NTSTATUS; "
|
|
|
|
|
"defaulting to STATUS_INVALID_NETWORK_RESPONSE\n", status);
|
2010-10-11 14:59:26 -04:00
|
|
|
case ERROR_BAD_NET_RESP: return STATUS_INVALID_NETWORK_RESPONSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-22 14:50:53 -05:00
|
|
|
void nfs41_create_volume_info(PFILE_FS_VOLUME_INFORMATION pVolInfo, DWORD *len)
|
|
|
|
|
{
|
|
|
|
|
DECLARE_CONST_UNICODE_STRING(VolName, VOL_NAME);
|
|
|
|
|
|
|
|
|
|
RtlZeroMemory(pVolInfo, sizeof(FILE_FS_VOLUME_INFORMATION));
|
|
|
|
|
pVolInfo->VolumeSerialNumber = 0xBABAFACE;
|
|
|
|
|
pVolInfo->VolumeLabelLength = VolName.Length;
|
|
|
|
|
RtlCopyMemory(&pVolInfo->VolumeLabel[0], (PVOID)VolName.Buffer,
|
|
|
|
|
VolName.MaximumLength);
|
|
|
|
|
*len = sizeof(FILE_FS_VOLUME_INFORMATION) + VolName.Length;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_QueryVolumeInformation(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_INVALID_PARAMETER;
|
2011-12-21 15:53:17 -05:00
|
|
|
nfs41_updowncall_entry *entry;
|
|
|
|
|
ULONG RemainingLength = RxContext->Info.LengthRemaining, SizeUsed;
|
2010-10-11 14:59:26 -04:00
|
|
|
FS_INFORMATION_CLASS InfoClass = RxContext->Info.FsInformationClass;
|
|
|
|
|
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
|
2010-10-11 14:59:26 -04:00
|
|
|
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
|
2010-11-05 20:08:55 -04:00
|
|
|
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
|
2011-12-22 14:50:53 -05:00
|
|
|
NFS41GetDeviceExtension(RxContext, DevExt);
|
|
|
|
|
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
LARGE_INTEGER t1, t2;
|
|
|
|
|
t1 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_VOLUME_QUERY
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
|
|
|
|
print_queryvolume_args(RxContext);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
switch (InfoClass) {
|
2011-12-21 15:53:17 -05:00
|
|
|
case FileFsVolumeInformation:
|
2011-12-22 14:50:53 -05:00
|
|
|
if ((ULONG)RxContext->Info.LengthRemaining >= DevExt->VolAttrsLen) {
|
|
|
|
|
RtlCopyMemory(RxContext->Info.Buffer, DevExt->VolAttrs,
|
|
|
|
|
DevExt->VolAttrsLen);
|
|
|
|
|
RxContext->Info.LengthRemaining -= DevExt->VolAttrsLen;
|
2011-12-21 15:53:17 -05:00
|
|
|
status = STATUS_SUCCESS;
|
2011-12-22 14:50:53 -05:00
|
|
|
} else {
|
|
|
|
|
RxContext->InformationToReturn = DevExt->VolAttrsLen;
|
|
|
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
2011-12-22 14:50:53 -05:00
|
|
|
goto out;
|
2011-12-21 15:53:17 -05:00
|
|
|
case FileFsDeviceInformation:
|
|
|
|
|
{
|
|
|
|
|
PFILE_FS_DEVICE_INFORMATION pDevInfo = RxContext->Info.Buffer;
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
SizeUsed = sizeof(FILE_FS_DEVICE_INFORMATION);
|
|
|
|
|
if (RemainingLength < SizeUsed) {
|
|
|
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
|
RxContext->InformationToReturn = SizeUsed;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
pDevInfo->DeviceType = RxContext->pFcb->pNetRoot->DeviceType;
|
|
|
|
|
pDevInfo->Characteristics = FILE_REMOTE_DEVICE | FILE_DEVICE_IS_MOUNTED;
|
|
|
|
|
RxContext->Info.LengthRemaining -= SizeUsed;
|
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case FileFsAttributeInformation:
|
|
|
|
|
/* used cached fs attributes if available */
|
|
|
|
|
if (pVNetRootContext->FsAttrsLen) {
|
|
|
|
|
const LONG len = pVNetRootContext->FsAttrsLen;
|
|
|
|
|
if (RxContext->Info.LengthRemaining < len) {
|
|
|
|
|
RxContext->InformationToReturn = len;
|
2010-10-11 14:59:26 -04:00
|
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
2010-10-11 16:10:52 -04:00
|
|
|
goto out;
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
2011-12-21 15:53:17 -05:00
|
|
|
RtlCopyMemory(RxContext->Info.Buffer,
|
|
|
|
|
pVNetRootContext->FsAttrs, len);
|
|
|
|
|
RxContext->Info.LengthRemaining -= len;
|
2010-10-11 14:59:26 -04:00
|
|
|
status = STATUS_SUCCESS;
|
2010-10-11 16:10:52 -04:00
|
|
|
goto out;
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
2011-12-21 15:53:17 -05:00
|
|
|
/* else fall through and send the upcall */
|
|
|
|
|
case FileFsSizeInformation:
|
|
|
|
|
case FileFsFullSizeInformation:
|
|
|
|
|
break;
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
default:
|
|
|
|
|
print_error("unhandled fs query class %d\n", InfoClass);
|
|
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
|
|
|
goto out;
|
2010-10-11 16:10:52 -04:00
|
|
|
}
|
2011-12-06 17:19:46 -05:00
|
|
|
status = nfs41_UpcallCreate(NFS41_VOLUME_QUERY, &nfs41_fobx->sec_ctx,
|
2011-04-13 15:28:48 -04:00
|
|
|
pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
|
2012-02-13 16:08:21 -05:00
|
|
|
pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
|
2010-10-11 16:10:52 -04:00
|
|
|
if (status)
|
|
|
|
|
goto out;
|
|
|
|
|
entry->u.Volume.query = InfoClass;
|
|
|
|
|
entry->u.Volume.buf = RxContext->Info.Buffer;
|
|
|
|
|
entry->u.Volume.buf_len = RxContext->Info.LengthRemaining;
|
|
|
|
|
|
|
|
|
|
if (nfs41_UpcallWaitForReply(entry) != STATUS_SUCCESS) {
|
|
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
|
2010-10-11 16:10:52 -04:00
|
|
|
if (entry->status == STATUS_BUFFER_TOO_SMALL) {
|
|
|
|
|
RxContext->InformationToReturn = entry->u.Volume.buf_len;
|
|
|
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
|
} else if (entry->status == STATUS_SUCCESS) {
|
2010-10-12 09:51:06 -04:00
|
|
|
if (InfoClass == FileFsAttributeInformation) {
|
|
|
|
|
/* fill in the FileSystemName */
|
|
|
|
|
PFILE_FS_ATTRIBUTE_INFORMATION attrs =
|
|
|
|
|
(PFILE_FS_ATTRIBUTE_INFORMATION)RxContext->Info.Buffer;
|
|
|
|
|
DECLARE_CONST_UNICODE_STRING(FsName, FS_NAME);
|
|
|
|
|
entry->u.Volume.buf_len += FsName.Length;
|
2011-12-22 11:59:45 -05:00
|
|
|
if (entry->u.Volume.buf_len > (ULONG)RxContext->Info.LengthRemaining) {
|
2010-10-12 09:51:06 -04:00
|
|
|
RxContext->InformationToReturn = entry->u.Volume.buf_len;
|
|
|
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
RtlCopyMemory(attrs->FileSystemName, FsName.Buffer,
|
|
|
|
|
FsName.MaximumLength); /* 'MaximumLength' to include null */
|
|
|
|
|
attrs->FileSystemNameLength = FsName.Length;
|
|
|
|
|
|
|
|
|
|
/* save fs attributes with the vnetroot */
|
|
|
|
|
if (entry->u.Volume.buf_len <= FS_ATTR_LEN) {
|
|
|
|
|
RtlCopyMemory(&pVNetRootContext->FsAttrs,
|
|
|
|
|
RxContext->Info.Buffer, entry->u.Volume.buf_len);
|
|
|
|
|
pVNetRootContext->FsAttrsLen = entry->u.Volume.buf_len;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
InterlockedIncrement(&volume.sops);
|
|
|
|
|
InterlockedAdd64(&volume.size, entry->u.Volume.buf_len);
|
|
|
|
|
#endif
|
2010-10-11 16:10:52 -04:00
|
|
|
RxContext->Info.LengthRemaining -= entry->u.Volume.buf_len;
|
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
|
} else {
|
|
|
|
|
status = map_volume_errors(entry->status);
|
|
|
|
|
}
|
|
|
|
|
RxFreePool(entry);
|
|
|
|
|
out:
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
t2 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
InterlockedIncrement(&volume.tops);
|
|
|
|
|
InterlockedAdd64(&volume.ticks, t2.QuadPart - t1.QuadPart);
|
|
|
|
|
#ifdef ENABLE_INDV_TIMINGS
|
|
|
|
|
DbgP("nfs41_QueryVolumeInformation delta = %d op=%d sum=%d\n",
|
|
|
|
|
t2.QuadPart - t1.QuadPart, volume.tops, volume.ticks);
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_VOLUME_QUERY
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-08 18:24:19 -05:00
|
|
|
VOID nfs41_update_srvopen_list(
|
|
|
|
|
PMRX_SRV_OPEN SrvOpen,
|
|
|
|
|
ULONGLONG ChangeTime)
|
|
|
|
|
{
|
|
|
|
|
PLIST_ENTRY pEntry;
|
|
|
|
|
nfs41_srvopen_list_entry *cur;
|
|
|
|
|
ExAcquireFastMutex(&srvopenLock);
|
|
|
|
|
pEntry = openlist->head.Flink;
|
2012-02-13 16:08:21 -05:00
|
|
|
#if defined(DEBUG_FILE_SET) || defined(DEBUG_ACL_SET) || \
|
|
|
|
|
defined(DEBUG_WRITE) || defined(DEBUG_EA_SET)
|
2012-02-08 18:24:19 -05:00
|
|
|
DbgP("nfs41_update_srvopen_list: Looking for srv_open=%p\n", SrvOpen);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2012-02-08 18:24:19 -05:00
|
|
|
while (!IsListEmpty(&openlist->head)) {
|
|
|
|
|
cur = (nfs41_srvopen_list_entry *)CONTAINING_RECORD(pEntry,
|
|
|
|
|
nfs41_srvopen_list_entry, next);
|
|
|
|
|
if (cur->srv_open == SrvOpen &&
|
|
|
|
|
cur->ChangeTime != ChangeTime) {
|
2012-02-13 16:08:21 -05:00
|
|
|
#if defined(DEBUG_FILE_SET) || defined(DEBUG_ACL_SET) || \
|
|
|
|
|
defined(DEBUG_WRITE) || defined(DEBUG_EA_SET)
|
2012-02-08 18:24:19 -05:00
|
|
|
DbgP("nfs41_update_srvopen_list: Found match: updating %llu to "
|
|
|
|
|
"%llu\n", cur->ChangeTime, ChangeTime);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2012-02-08 18:24:19 -05:00
|
|
|
cur->ChangeTime = ChangeTime;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* place an upcall for this srv_open */
|
|
|
|
|
if (pEntry->Flink == &openlist->head) {
|
2012-02-13 16:08:21 -05:00
|
|
|
#if defined(DEBUG_FILE_SET) || defined(DEBUG_ACL_SET) || \
|
|
|
|
|
defined(DEBUG_WRITE) || defined(DEBUG_EA_SET)
|
2012-02-08 18:24:19 -05:00
|
|
|
DbgP("nfs41_update_srvopen_list: reached end of the list\n");
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2012-02-08 18:24:19 -05:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
pEntry = pEntry->Flink;
|
|
|
|
|
}
|
|
|
|
|
ExReleaseFastMutex(&srvopenLock);
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
void print_nfs3_attrs(
|
|
|
|
|
nfs3_attrs *attrs)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
DbgP("type=%d mode=%o nlink=%d size=%d atime=%x mtime=%x ctime=%x\n",
|
|
|
|
|
attrs->type, attrs->mode, attrs->nlink, attrs->size, attrs->atime,
|
|
|
|
|
attrs->mtime, attrs->ctime);
|
|
|
|
|
}
|
2010-10-27 14:58:35 -04:00
|
|
|
|
|
|
|
|
void file_time_to_nfs_time(
|
|
|
|
|
IN const PLARGE_INTEGER file_time,
|
|
|
|
|
OUT LONGLONG *nfs_time)
|
|
|
|
|
{
|
|
|
|
|
LARGE_INTEGER diff = unix_time_diff;
|
|
|
|
|
diff.QuadPart = file_time->QuadPart - diff.QuadPart;
|
|
|
|
|
*nfs_time = diff.QuadPart / 10000000;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
void create_nfs3_attrs(
|
|
|
|
|
nfs3_attrs *attrs,
|
|
|
|
|
PNFS41_FCB nfs41_fcb)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
RtlZeroMemory(attrs, sizeof(nfs3_attrs));
|
2010-10-19 15:28:29 -04:00
|
|
|
if (nfs41_fcb->BasicInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
|
|
|
|
|
attrs->type = NF3LNK;
|
|
|
|
|
else if (nfs41_fcb->StandardInfo.Directory)
|
2010-10-11 14:59:26 -04:00
|
|
|
attrs->type = NF3DIR;
|
|
|
|
|
else
|
|
|
|
|
attrs->type = NF3REG;
|
|
|
|
|
attrs->mode = nfs41_fcb->mode;
|
|
|
|
|
attrs->nlink = nfs41_fcb->StandardInfo.NumberOfLinks;
|
|
|
|
|
attrs->size.QuadPart = attrs->used.QuadPart =
|
|
|
|
|
nfs41_fcb->StandardInfo.EndOfFile.QuadPart;
|
2010-10-27 14:58:35 -04:00
|
|
|
file_time_to_nfs_time(&nfs41_fcb->BasicInfo.LastAccessTime, &attrs->atime);
|
|
|
|
|
file_time_to_nfs_time(&nfs41_fcb->BasicInfo.ChangeTime, &attrs->mtime);
|
|
|
|
|
file_time_to_nfs_time(&nfs41_fcb->BasicInfo.CreationTime, &attrs->ctime);
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
|
2011-09-22 14:56:11 -04:00
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS map_setea_error(
|
|
|
|
|
DWORD error)
|
2011-09-22 14:56:11 -04:00
|
|
|
{
|
|
|
|
|
switch (error) {
|
|
|
|
|
case NO_ERROR: return STATUS_SUCCESS;
|
|
|
|
|
case ERROR_NOT_EMPTY: return STATUS_DIRECTORY_NOT_EMPTY;
|
|
|
|
|
case ERROR_FILE_EXISTS: return STATUS_OBJECT_NAME_COLLISION;
|
|
|
|
|
case ERROR_FILE_NOT_FOUND: return STATUS_OBJECT_NAME_NOT_FOUND;
|
|
|
|
|
case ERROR_PATH_NOT_FOUND: return STATUS_OBJECT_PATH_NOT_FOUND;
|
|
|
|
|
case ERROR_ACCESS_DENIED: return STATUS_ACCESS_DENIED;
|
|
|
|
|
case ERROR_NOT_SUPPORTED: return STATUS_NOT_IMPLEMENTED;
|
|
|
|
|
case ERROR_NETWORK_ACCESS_DENIED: return STATUS_NETWORK_ACCESS_DENIED;
|
|
|
|
|
case ERROR_NETNAME_DELETED: return STATUS_NETWORK_NAME_DELETED;
|
|
|
|
|
case ERROR_BUFFER_OVERFLOW: return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
default:
|
|
|
|
|
print_error("failed to map windows error %d to NTSTATUS; "
|
|
|
|
|
"defaulting to STATUS_INVALID_PARAMETER\n", error);
|
|
|
|
|
case ERROR_INVALID_PARAMETER: return STATUS_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_SetEaInformation(
|
|
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
2011-09-22 14:56:11 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_EAS_NOT_SUPPORTED;
|
|
|
|
|
nfs41_updowncall_entry *entry;
|
|
|
|
|
PUNICODE_STRING FileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PFILE_FULL_EA_INFORMATION eainfo =
|
2011-09-22 14:56:11 -04:00
|
|
|
(PFILE_FULL_EA_INFORMATION)RxContext->Info.Buffer;
|
|
|
|
|
nfs3_attrs *attrs = NULL;
|
|
|
|
|
ULONG buflen = RxContext->CurrentIrpSp->Parameters.SetEa.Length, error_offset;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
|
|
|
|
|
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
|
|
|
|
|
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
|
|
|
|
|
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
|
|
|
|
|
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
|
|
|
|
__notnull PNFS41_FCB nfs41_fcb = NFS41GetFcbExtension(RxContext->pFcb);
|
|
|
|
|
__notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
|
2011-09-22 14:56:11 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
LARGE_INTEGER t1, t2;
|
|
|
|
|
t1 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_EA_SET
|
2011-09-22 14:56:11 -04:00
|
|
|
DbgEn();
|
|
|
|
|
print_debug_header(RxContext);
|
|
|
|
|
print_ea_info(1, eainfo);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-09-22 14:56:11 -04:00
|
|
|
|
2011-10-04 10:57:06 -04:00
|
|
|
if (pVNetRootContext->read_only) {
|
|
|
|
|
DbgP("Read-only mount\n");
|
|
|
|
|
status = STATUS_ACCESS_DENIED;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-06 17:19:46 -05:00
|
|
|
status = nfs41_UpcallCreate(NFS41_EA_SET, &nfs41_fobx->sec_ctx,
|
2011-09-22 14:56:11 -04:00
|
|
|
pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
|
2012-02-13 16:08:21 -05:00
|
|
|
pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
|
2011-09-22 14:56:11 -04:00
|
|
|
if (status)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
if (AnsiStrEq(&NfsV3Attributes, eainfo->EaName, eainfo->EaNameLength)) {
|
|
|
|
|
attrs = (nfs3_attrs *)(eainfo->EaName + eainfo->EaNameLength + 1);
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_EA_SET
|
2011-09-22 14:56:11 -04:00
|
|
|
print_nfs3_attrs(attrs);
|
|
|
|
|
DbgP("old mode is %o new mode is %o\n", nfs41_fcb->mode, attrs->mode);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-09-22 14:56:11 -04:00
|
|
|
entry->u.SetEa.mode = nfs41_fcb->mode = attrs->mode;
|
|
|
|
|
} else {
|
|
|
|
|
entry->u.SetEa.mode = 0;
|
|
|
|
|
status = IoCheckEaBufferValidity(eainfo, buflen, &error_offset);
|
|
|
|
|
if (status) {
|
|
|
|
|
RxFreePool(entry);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
entry->u.SetEa.buf = eainfo;
|
|
|
|
|
entry->u.SetEa.buf_len = buflen;
|
|
|
|
|
entry->u.SetEa.filename = FileName;
|
|
|
|
|
|
|
|
|
|
if (nfs41_UpcallWaitForReply(entry) != STATUS_SUCCESS) {
|
|
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
if (entry->status == STATUS_SUCCESS) {
|
|
|
|
|
InterlockedIncrement(&setexattr.sops);
|
|
|
|
|
InterlockedAdd64(&setexattr.size, entry->u.SetEa.buf_len);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
status = map_setea_error(entry->status);
|
2012-02-08 18:24:19 -05:00
|
|
|
if (!status) {
|
|
|
|
|
if (!nfs41_fobx->deleg_type && entry->u.SetEa.ChangeTime &&
|
|
|
|
|
(SrvOpen->DesiredAccess &
|
|
|
|
|
(FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA)))
|
|
|
|
|
nfs41_update_srvopen_list(SrvOpen, entry->u.SetEa.ChangeTime);
|
|
|
|
|
nfs41_fcb->changeattr = entry->u.SetEa.ChangeTime;
|
|
|
|
|
}
|
2011-09-22 14:56:11 -04:00
|
|
|
RxFreePool(entry);
|
|
|
|
|
out:
|
|
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
t2 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
InterlockedIncrement(&setexattr.tops);
|
|
|
|
|
InterlockedAdd64(&setexattr.ticks, t2.QuadPart - t1.QuadPart);
|
|
|
|
|
#ifdef ENABLE_INDV_TIMINGS
|
|
|
|
|
DbgP("nfs41_SetEaInformation delta = %d op=%d sum=%d\n",
|
|
|
|
|
t2.QuadPart - t1.QuadPart, setexattr.tops, setexattr.ticks);
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_EA_SET
|
2011-09-22 14:56:11 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-09-22 14:56:11 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_QueryEaInformation(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_EAS_NOT_SUPPORTED;
|
2011-12-21 15:53:17 -05:00
|
|
|
nfs41_updowncall_entry *entry;
|
2010-10-11 14:59:26 -04:00
|
|
|
PFILE_GET_EA_INFORMATION query = (PFILE_GET_EA_INFORMATION)
|
2011-09-22 14:56:11 -04:00
|
|
|
RxContext->CurrentIrpSp->Parameters.QueryEa.EaList;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PFILE_FULL_EA_INFORMATION info =
|
|
|
|
|
(PFILE_FULL_EA_INFORMATION)RxContext->Info.Buffer;
|
2011-09-22 14:56:11 -04:00
|
|
|
PUNICODE_STRING FileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
|
|
|
|
|
ULONG buflen = RxContext->CurrentIrpSp->Parameters.QueryEa.Length;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
|
|
|
|
|
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
|
|
|
|
|
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
|
|
|
|
|
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
|
|
|
|
|
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
|
|
|
|
__notnull PNFS41_FCB nfs41_fcb = NFS41GetFcbExtension(RxContext->pFcb);
|
|
|
|
|
__notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
|
2011-09-22 14:56:11 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
LARGE_INTEGER t1, t2;
|
|
|
|
|
t1 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_EA_QUERY
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
|
|
|
|
print_debug_header(RxContext);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-12-21 15:53:17 -05:00
|
|
|
if (RxContext->CurrentIrpSp->Parameters.QueryEa.EaList == NULL)
|
|
|
|
|
goto out;
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_EA_QUERY
|
2011-12-21 15:53:17 -05:00
|
|
|
print_get_ea(1, query);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
if (AnsiStrEq(&NfsV3Attributes, query->EaName, query->EaNameLength)) {
|
|
|
|
|
nfs3_attrs attrs;
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
const LONG LengthRequired = sizeof(FILE_FULL_EA_INFORMATION) +
|
|
|
|
|
NfsV3Attributes.Length + sizeof(nfs3_attrs) - sizeof(CHAR);
|
|
|
|
|
if (LengthRequired > RxContext->Info.LengthRemaining) {
|
|
|
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
|
RxContext->InformationToReturn = LengthRequired;
|
2011-09-22 14:56:11 -04:00
|
|
|
goto out;
|
2011-12-21 15:53:17 -05:00
|
|
|
}
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
create_nfs3_attrs(&attrs, nfs41_fcb);
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_EA_QUERY
|
2011-12-21 15:53:17 -05:00
|
|
|
print_nfs3_attrs(&attrs);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-12-21 15:53:17 -05:00
|
|
|
|
|
|
|
|
info->NextEntryOffset = 0;
|
|
|
|
|
info->Flags = 0;
|
|
|
|
|
info->EaNameLength = (UCHAR)NfsV3Attributes.Length;
|
|
|
|
|
info->EaValueLength = sizeof(nfs3_attrs);
|
|
|
|
|
RtlCopyMemory(info->EaName, NfsV3Attributes.Buffer,
|
|
|
|
|
NfsV3Attributes.Length);
|
|
|
|
|
RtlCopyMemory(info->EaName + info->EaNameLength + 1, &attrs,
|
|
|
|
|
sizeof(nfs3_attrs));
|
|
|
|
|
RxContext->Info.LengthRemaining = LengthRequired;
|
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (AnsiStrEq(&NfsActOnLink, query->EaName, query->EaNameLength) ||
|
|
|
|
|
AnsiStrEq(&NfsSymlinkTargetName, query->EaName,
|
|
|
|
|
query->EaNameLength)) {
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
const LONG LengthRequired = sizeof(FILE_FULL_EA_INFORMATION) +
|
|
|
|
|
NfsActOnLink.Length - sizeof(CHAR);
|
|
|
|
|
if (LengthRequired > RxContext->Info.LengthRemaining) {
|
|
|
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
|
RxContext->InformationToReturn = LengthRequired;
|
2011-09-22 14:56:11 -04:00
|
|
|
goto out;
|
2011-12-06 17:19:46 -05:00
|
|
|
}
|
2011-09-22 14:56:11 -04:00
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
info->NextEntryOffset = 0;
|
|
|
|
|
info->Flags = 0;
|
|
|
|
|
info->EaNameLength = (UCHAR)NfsActOnLink.Length;
|
|
|
|
|
info->EaValueLength = 0;
|
|
|
|
|
RtlCopyMemory(info->EaName, NfsActOnLink.Buffer, NfsActOnLink.Length);
|
|
|
|
|
RxContext->Info.LengthRemaining = LengthRequired;
|
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
status = nfs41_UpcallCreate(NFS41_EA_GET, &nfs41_fobx->sec_ctx,
|
|
|
|
|
pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
|
2012-02-13 16:08:21 -05:00
|
|
|
pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
|
2011-12-21 15:53:17 -05:00
|
|
|
if (status)
|
|
|
|
|
goto out;
|
|
|
|
|
entry->u.QueryEa.filename = FileName;
|
|
|
|
|
entry->u.QueryEa.buf_len = buflen;
|
|
|
|
|
entry->u.QueryEa.buf = RxContext->Info.Buffer;
|
|
|
|
|
entry->u.QueryEa.EaList = query;
|
|
|
|
|
entry->u.QueryEa.EaListLength = RxContext->QueryEa.UserEaListLength;
|
|
|
|
|
entry->u.QueryEa.EaIndex = RxContext->QueryEa.UserEaIndex;
|
|
|
|
|
entry->u.QueryEa.RestartScan = RxContext->QueryEa.RestartScan;
|
|
|
|
|
entry->u.QueryEa.ReturnSingleEntry = RxContext->QueryEa.ReturnSingleEntry;
|
|
|
|
|
|
|
|
|
|
if (nfs41_UpcallWaitForReply(entry) != STATUS_SUCCESS) {
|
|
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (entry->status == STATUS_BUFFER_TOO_SMALL) {
|
|
|
|
|
RxContext->InformationToReturn = entry->u.QueryEa.buf_len;
|
|
|
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
|
} else if (entry->status == STATUS_SUCCESS) {
|
|
|
|
|
RxContext->Info.LengthRemaining = entry->u.QueryEa.buf_len;
|
|
|
|
|
RxContext->IoStatusBlock.Status = STATUS_SUCCESS;
|
2011-09-22 14:56:11 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
2011-12-21 15:53:17 -05:00
|
|
|
InterlockedIncrement(&getexattr.sops);
|
|
|
|
|
InterlockedAdd64(&getexattr.size, entry->u.QueryEa.buf_len);
|
2011-09-22 14:56:11 -04:00
|
|
|
#endif
|
2011-12-21 15:53:17 -05:00
|
|
|
} else {
|
|
|
|
|
status = map_setea_error(entry->status);
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
2011-12-21 15:53:17 -05:00
|
|
|
RxFreePool(entry);
|
2010-10-11 14:59:26 -04:00
|
|
|
out:
|
2011-09-22 14:56:11 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
t2 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
InterlockedIncrement(&getexattr.tops);
|
|
|
|
|
InterlockedAdd64(&getexattr.ticks, t2.QuadPart - t1.QuadPart);
|
|
|
|
|
#ifdef ENABLE_INDV_TIMINGS
|
|
|
|
|
DbgP("nfs41_QueryEaInformation delta = %d op=%d sum=%d\n",
|
|
|
|
|
t2.QuadPart - t1.QuadPart, getexattr.tops, getexattr.ticks);
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_EA_QUERY
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
2011-04-12 15:56:20 -04:00
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS map_query_acl_error(
|
|
|
|
|
DWORD error)
|
2011-03-15 16:31:52 -04:00
|
|
|
{
|
|
|
|
|
switch (error) {
|
2011-04-12 15:56:20 -04:00
|
|
|
case NO_ERROR: return STATUS_SUCCESS;
|
2011-03-15 16:31:52 -04:00
|
|
|
case ERROR_NOT_SUPPORTED: return STATUS_NOT_SUPPORTED;
|
|
|
|
|
case ERROR_ACCESS_DENIED: return STATUS_ACCESS_DENIED;
|
|
|
|
|
case ERROR_FILE_NOT_FOUND: return STATUS_OBJECT_NAME_NOT_FOUND;
|
|
|
|
|
case ERROR_INVALID_PARAMETER: return STATUS_INVALID_PARAMETER;
|
|
|
|
|
default:
|
|
|
|
|
print_error("failed to map windows error %d to NTSTATUS; "
|
|
|
|
|
"defaulting to STATUS_INVALID_NETWORK_RESPONSE\n", error);
|
|
|
|
|
case ERROR_BAD_NET_RESP: return STATUS_INVALID_NETWORK_RESPONSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-04-12 15:56:20 -04:00
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_QuerySecurityInformation(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS status = STATUS_NOT_SUPPORTED;
|
2011-03-15 16:31:52 -04:00
|
|
|
nfs41_updowncall_entry *entry;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
|
2011-03-15 16:31:52 -04:00
|
|
|
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
|
2011-03-15 16:31:52 -04:00
|
|
|
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
|
2011-03-15 16:31:52 -04:00
|
|
|
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
2011-04-12 15:56:20 -04:00
|
|
|
SECURITY_INFORMATION info_class =
|
|
|
|
|
RxContext->CurrentIrpSp->Parameters.QuerySecurity.SecurityInformation;
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
LARGE_INTEGER t1, t2;
|
|
|
|
|
t1 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
#endif
|
2011-03-15 16:31:52 -04:00
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_ACL_QUERY
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
2011-03-15 16:31:52 -04:00
|
|
|
print_debug_header(RxContext);
|
2011-04-12 15:56:20 -04:00
|
|
|
print_acl_args(info_class);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-04-12 15:56:20 -04:00
|
|
|
|
|
|
|
|
/* we don't support sacls */
|
2011-08-24 13:22:51 -04:00
|
|
|
if (info_class == SACL_SECURITY_INFORMATION ||
|
|
|
|
|
info_class == LABEL_SECURITY_INFORMATION)
|
2011-04-12 15:56:20 -04:00
|
|
|
goto out;
|
2011-03-15 16:31:52 -04:00
|
|
|
|
2011-08-24 12:23:04 -04:00
|
|
|
if (nfs41_fobx->acl && nfs41_fobx->acl_len) {
|
|
|
|
|
LARGE_INTEGER current_time;
|
|
|
|
|
KeQuerySystemTime(¤t_time);
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_ACL_QUERY
|
|
|
|
|
DbgP("CurrentTime %lx Saved Acl time %lx\n",
|
2011-08-24 12:23:04 -04:00
|
|
|
current_time.QuadPart, nfs41_fobx->time.QuadPart);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-08-24 12:23:04 -04:00
|
|
|
if (current_time.QuadPart - nfs41_fobx->time.QuadPart <= 20*1000) {
|
2011-09-23 12:12:45 -04:00
|
|
|
PSECURITY_DESCRIPTOR sec_desc = (PSECURITY_DESCRIPTOR)
|
|
|
|
|
RxContext->CurrentIrp->UserBuffer;
|
|
|
|
|
RtlCopyMemory(sec_desc, nfs41_fobx->acl, nfs41_fobx->acl_len);
|
|
|
|
|
RxContext->IoStatusBlock.Information =
|
|
|
|
|
RxContext->InformationToReturn = nfs41_fobx->acl_len;
|
|
|
|
|
RxContext->IoStatusBlock.Status = status = STATUS_SUCCESS;
|
2011-09-22 17:07:44 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
2011-09-23 12:12:45 -04:00
|
|
|
InterlockedIncrement(&getacl.sops);
|
|
|
|
|
InterlockedAdd64(&getacl.size, nfs41_fobx->acl_len);
|
2011-09-22 17:07:44 -04:00
|
|
|
#endif
|
2011-08-24 12:23:04 -04:00
|
|
|
}
|
|
|
|
|
RxFreePool(nfs41_fobx->acl);
|
|
|
|
|
nfs41_fobx->acl = NULL;
|
|
|
|
|
nfs41_fobx->acl_len = 0;
|
|
|
|
|
if (!status)
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-13 15:28:48 -04:00
|
|
|
status = nfs41_UpcallCreate(NFS41_ACL_QUERY, &nfs41_fobx->sec_ctx,
|
|
|
|
|
pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
|
2012-02-13 16:08:21 -05:00
|
|
|
pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
|
2011-03-15 16:31:52 -04:00
|
|
|
if (status)
|
|
|
|
|
goto out;
|
2011-04-08 20:19:59 -04:00
|
|
|
entry->u.Acl.query = info_class;
|
|
|
|
|
/* we can't provide RxContext->CurrentIrp->UserBuffer to the upcall thread
|
|
|
|
|
* because it becomes an invalid pointer with that execution context
|
|
|
|
|
*/
|
|
|
|
|
entry->u.Acl.buf_len = RxContext->CurrentIrpSp->Parameters.QuerySecurity.Length;
|
2011-03-15 16:31:52 -04:00
|
|
|
|
|
|
|
|
if (nfs41_UpcallWaitForReply(entry) != STATUS_SUCCESS) {
|
|
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (entry->status == STATUS_BUFFER_TOO_SMALL) {
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_ACL_QUERY
|
2011-12-21 15:53:17 -05:00
|
|
|
DbgP("nfs41_QuerySecurityInformation: provided buffer size=%d but we "
|
|
|
|
|
"need %d\n",
|
|
|
|
|
RxContext->CurrentIrpSp->Parameters.QuerySecurity.Length,
|
|
|
|
|
entry->u.Acl.buf_len);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-05-02 13:38:41 -04:00
|
|
|
status = STATUS_BUFFER_OVERFLOW;
|
2011-04-08 20:19:59 -04:00
|
|
|
RxContext->InformationToReturn = entry->u.Acl.buf_len;
|
2011-08-24 12:23:04 -04:00
|
|
|
|
|
|
|
|
/* Save ACL buffer */
|
|
|
|
|
nfs41_fobx->acl = entry->u.Acl.buf;
|
|
|
|
|
nfs41_fobx->acl_len = entry->u.Acl.buf_len;
|
|
|
|
|
KeQuerySystemTime(&nfs41_fobx->time);
|
2011-03-15 16:31:52 -04:00
|
|
|
} else if (entry->status == STATUS_SUCCESS) {
|
2011-09-23 12:12:45 -04:00
|
|
|
PSECURITY_DESCRIPTOR sec_desc = (PSECURITY_DESCRIPTOR)
|
|
|
|
|
RxContext->CurrentIrp->UserBuffer;
|
|
|
|
|
RtlCopyMemory(sec_desc, entry->u.Acl.buf, entry->u.Acl.buf_len);
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
InterlockedIncrement(&getacl.sops);
|
|
|
|
|
InterlockedAdd64(&getacl.size, entry->u.Acl.buf_len);
|
|
|
|
|
#endif
|
2011-04-08 20:19:59 -04:00
|
|
|
RxFreePool(entry->u.Acl.buf);
|
2011-08-24 12:23:04 -04:00
|
|
|
nfs41_fobx->acl = NULL;
|
|
|
|
|
nfs41_fobx->acl_len = 0;
|
2011-03-15 16:31:52 -04:00
|
|
|
RxContext->IoStatusBlock.Information = RxContext->InformationToReturn =
|
2011-04-08 20:19:59 -04:00
|
|
|
entry->u.Acl.buf_len;
|
2011-09-23 12:12:45 -04:00
|
|
|
RxContext->IoStatusBlock.Status = status = STATUS_SUCCESS;
|
2011-03-15 16:31:52 -04:00
|
|
|
} else {
|
|
|
|
|
status = map_query_acl_error(entry->status);
|
|
|
|
|
}
|
|
|
|
|
RxFreePool(entry);
|
|
|
|
|
out:
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
t2 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
/* only count getacl that we made an upcall for */
|
|
|
|
|
if (status == STATUS_BUFFER_OVERFLOW) {
|
|
|
|
|
InterlockedIncrement(&getacl.tops);
|
|
|
|
|
InterlockedAdd64(&getacl.ticks, t2.QuadPart - t1.QuadPart);
|
|
|
|
|
}
|
|
|
|
|
#ifdef ENABLE_INDV_TIMINGS
|
|
|
|
|
DbgP("nfs41_QuerySecurityInformation: delta = %d op=%d sum=%d\n",
|
|
|
|
|
t2.QuadPart - t1.QuadPart, getacl.tops, getacl.ticks);
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_ACL_QUERY
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_SetSecurityInformation(
|
|
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS status = STATUS_NOT_SUPPORTED;
|
2011-04-12 15:56:20 -04:00
|
|
|
nfs41_updowncall_entry *entry;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
|
2011-04-12 15:56:20 -04:00
|
|
|
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
|
2011-04-12 15:56:20 -04:00
|
|
|
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
|
2011-04-12 15:56:20 -04:00
|
|
|
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PSECURITY_DESCRIPTOR sec_desc =
|
|
|
|
|
RxContext->CurrentIrpSp->Parameters.SetSecurity.SecurityDescriptor;
|
2012-02-08 18:24:19 -05:00
|
|
|
__notnull PNFS41_FCB nfs41_fcb = NFS41GetFcbExtension(RxContext->pFcb);
|
2011-04-12 15:56:20 -04:00
|
|
|
SECURITY_INFORMATION info_class =
|
|
|
|
|
RxContext->CurrentIrpSp->Parameters.SetSecurity.SecurityInformation;
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
LARGE_INTEGER t1, t2;
|
|
|
|
|
t1 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_ACL_SET
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
2011-04-12 15:56:20 -04:00
|
|
|
print_debug_header(RxContext);
|
|
|
|
|
print_acl_args(info_class);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-04-12 15:56:20 -04:00
|
|
|
|
2011-10-04 10:57:06 -04:00
|
|
|
if (pVNetRootContext->read_only) {
|
|
|
|
|
DbgP("Read-only mount\n");
|
|
|
|
|
status = STATUS_ACCESS_DENIED;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-12 15:56:20 -04:00
|
|
|
/* check that ACL is present */
|
|
|
|
|
if (info_class & DACL_SECURITY_INFORMATION) {
|
|
|
|
|
PACL acl;
|
|
|
|
|
BOOLEAN present, dacl_default;
|
2011-12-21 15:53:17 -05:00
|
|
|
status = RtlGetDaclSecurityDescriptor(sec_desc, &present, &acl,
|
|
|
|
|
&dacl_default);
|
2011-04-12 15:56:20 -04:00
|
|
|
if (status) {
|
|
|
|
|
DbgP("RtlGetDaclSecurityDescriptor failed %x\n", status);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
if (present == FALSE) {
|
|
|
|
|
DbgP("NO ACL present\n");
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* we don't support sacls */
|
2011-08-24 13:22:51 -04:00
|
|
|
if (info_class == SACL_SECURITY_INFORMATION ||
|
|
|
|
|
info_class == LABEL_SECURITY_INFORMATION)
|
2011-04-12 15:56:20 -04:00
|
|
|
goto out;
|
|
|
|
|
|
2011-04-13 15:28:48 -04:00
|
|
|
status = nfs41_UpcallCreate(NFS41_ACL_SET, &nfs41_fobx->sec_ctx,
|
|
|
|
|
pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
|
2012-02-13 16:08:21 -05:00
|
|
|
pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
|
2011-04-12 15:56:20 -04:00
|
|
|
if (status)
|
|
|
|
|
goto out;
|
2011-04-08 20:19:59 -04:00
|
|
|
entry->u.Acl.query = info_class;
|
|
|
|
|
entry->u.Acl.buf = sec_desc;
|
|
|
|
|
entry->u.Acl.buf_len = RtlLengthSecurityDescriptor(sec_desc);
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
InterlockedIncrement(&setacl.sops);
|
|
|
|
|
InterlockedAdd64(&setacl.size, entry->u.Acl.buf_len);
|
|
|
|
|
#endif
|
2011-04-12 15:56:20 -04:00
|
|
|
|
|
|
|
|
if (nfs41_UpcallWaitForReply(entry) != STATUS_SUCCESS) {
|
|
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
status = map_query_acl_error(entry->status);
|
2012-02-08 18:24:19 -05:00
|
|
|
if (!status) {
|
|
|
|
|
if (!nfs41_fobx->deleg_type && entry->u.Acl.ChangeTime &&
|
|
|
|
|
(SrvOpen->DesiredAccess &
|
|
|
|
|
(FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA)))
|
|
|
|
|
nfs41_update_srvopen_list(SrvOpen, entry->u.Acl.ChangeTime);
|
|
|
|
|
nfs41_fcb->changeattr = entry->u.Acl.ChangeTime;
|
|
|
|
|
}
|
2011-04-12 15:56:20 -04:00
|
|
|
RxFreePool(entry);
|
|
|
|
|
out:
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
t2 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
InterlockedIncrement(&setacl.tops);
|
|
|
|
|
InterlockedAdd64(&setacl.ticks, t2.QuadPart - t1.QuadPart);
|
|
|
|
|
#ifdef ENABLE_INDV_TIMINGS
|
|
|
|
|
DbgP("nfs41_SetSecurityInformation delta = %d op=%d sum=%d\n",
|
|
|
|
|
t2.QuadPart - t1.QuadPart, setacl.tops, setacl.ticks);
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_ACL_SET
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS map_queryfile_error(
|
|
|
|
|
DWORD error)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
switch (error) {
|
|
|
|
|
case ERROR_ACCESS_DENIED: return STATUS_ACCESS_DENIED;
|
|
|
|
|
case ERROR_NETNAME_DELETED: return STATUS_NETWORK_NAME_DELETED;
|
|
|
|
|
case ERROR_INVALID_PARAMETER: return STATUS_INVALID_PARAMETER;
|
|
|
|
|
default:
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("failed to map windows error %d to NTSTATUS; "
|
|
|
|
|
"defaulting to STATUS_INVALID_NETWORK_RESPONSE\n", error);
|
2010-10-11 14:59:26 -04:00
|
|
|
case ERROR_BAD_NET_RESP: return STATUS_INVALID_NETWORK_RESPONSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_QueryFileInformation(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_OBJECT_NAME_NOT_FOUND;
|
|
|
|
|
FILE_INFORMATION_CLASS InfoClass = RxContext->Info.FileInformationClass;
|
|
|
|
|
nfs41_updowncall_entry *entry;
|
|
|
|
|
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
|
2010-10-11 14:59:26 -04:00
|
|
|
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
|
2010-11-05 20:08:55 -04:00
|
|
|
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_FCB nfs41_fcb = NFS41GetFcbExtension(RxContext->pFcb);
|
|
|
|
|
__notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
LARGE_INTEGER t1, t2;
|
|
|
|
|
t1 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_FILE_QUERY
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
2012-02-13 16:08:21 -05:00
|
|
|
print_debug_filedirquery_header(RxContext);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
switch (InfoClass) {
|
|
|
|
|
case FileEaInformation:
|
|
|
|
|
{
|
|
|
|
|
PFILE_EA_INFORMATION info =
|
|
|
|
|
(PFILE_EA_INFORMATION)RxContext->Info.Buffer;
|
|
|
|
|
info->EaSize = 0;
|
|
|
|
|
RxContext->Info.LengthRemaining -= sizeof(FILE_EA_INFORMATION);
|
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
#ifdef FCB_ATTR_CACHING
|
|
|
|
|
case FileBasicInformation:
|
|
|
|
|
if(nfs41_fcb->Flags & FCB_BASIC_INFO_CACHED) {
|
|
|
|
|
RtlCopyMemory(RxContext->Info.Buffer, &nfs41_fcb->BasicInfo,
|
|
|
|
|
sizeof(nfs41_fcb->BasicInfo));
|
|
|
|
|
RxContext->Info.LengthRemaining -= sizeof(nfs41_fcb->BasicInfo);
|
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case FileStandardInformation:
|
|
|
|
|
if(nfs41_fcb->Flags & FCB_STANDARD_INFO_CACHED) {
|
|
|
|
|
RtlCopyMemory(RxContext->Info.Buffer, &nfs41_fcb->StandardInfo,
|
|
|
|
|
sizeof(nfs41_fcb->StandardInfo));
|
|
|
|
|
RxContext->Info.LengthRemaining -= sizeof(nfs41_fcb->StandardInfo);
|
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
#else
|
|
|
|
|
case FileBasicInformation:
|
|
|
|
|
case FileStandardInformation:
|
|
|
|
|
#endif
|
2011-03-30 14:21:40 -04:00
|
|
|
case FileInternalInformation:
|
2010-10-11 14:59:26 -04:00
|
|
|
case FileAttributeTagInformation:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("unhandled file query class %d\n", InfoClass);
|
2010-10-11 14:59:26 -04:00
|
|
|
status = STATUS_INVALID_PARAMETER;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-13 15:28:48 -04:00
|
|
|
status = nfs41_UpcallCreate(NFS41_FILE_QUERY, &nfs41_fobx->sec_ctx,
|
|
|
|
|
pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
|
2012-02-13 16:08:21 -05:00
|
|
|
pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (status)
|
|
|
|
|
goto out;
|
|
|
|
|
entry->u.QueryFile.InfoClass = InfoClass;
|
|
|
|
|
entry->u.QueryFile.buf = RxContext->Info.Buffer;
|
|
|
|
|
entry->u.QueryFile.buf_len = RxContext->Info.LengthRemaining;
|
|
|
|
|
|
|
|
|
|
if (nfs41_UpcallWaitForReply(entry) != STATUS_SUCCESS) {
|
|
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (entry->status == STATUS_BUFFER_TOO_SMALL) {
|
|
|
|
|
RxContext->InformationToReturn = entry->u.QueryFile.buf_len;
|
|
|
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
|
} else if (entry->status == STATUS_SUCCESS) {
|
|
|
|
|
BOOLEAN DeletePending = FALSE;
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
InterlockedIncrement(&getattr.sops);
|
|
|
|
|
InterlockedAdd64(&getattr.size, entry->u.QueryFile.buf_len);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
RxContext->Info.LengthRemaining -= entry->u.QueryFile.buf_len;
|
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
|
|
|
|
|
|
switch (InfoClass) {
|
|
|
|
|
case FileBasicInformation:
|
|
|
|
|
RtlCopyMemory(&nfs41_fcb->BasicInfo, RxContext->Info.Buffer,
|
|
|
|
|
sizeof(nfs41_fcb->BasicInfo));
|
|
|
|
|
nfs41_fcb->Flags |= FCB_BASIC_INFO_CACHED;
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_FILE_QUERY
|
2010-10-11 14:59:26 -04:00
|
|
|
print_basic_info(1, &nfs41_fcb->BasicInfo);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
break;
|
|
|
|
|
case FileStandardInformation:
|
|
|
|
|
#ifndef FCB_ATTR_CACHING
|
|
|
|
|
/* this a fix for RDBSS behaviour when it first calls ExtendForCache,
|
|
|
|
|
* then it sends a file query irp for standard attributes and
|
|
|
|
|
* expects to receive EndOfFile of value set by the ExtendForCache.
|
|
|
|
|
* It seems to cache the filesize based on that instead of sending
|
|
|
|
|
* a file size query for after doing the write.
|
|
|
|
|
*/
|
|
|
|
|
{
|
|
|
|
|
PFILE_STANDARD_INFORMATION std_info;
|
|
|
|
|
std_info = (PFILE_STANDARD_INFORMATION)RxContext->Info.Buffer;
|
|
|
|
|
if (nfs41_fcb->StandardInfo.AllocationSize.QuadPart >
|
|
|
|
|
std_info->AllocationSize.QuadPart) {
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_FILE_QUERY
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgP("Old AllocationSize is bigger: saving %x\n",
|
|
|
|
|
nfs41_fcb->StandardInfo.AllocationSize.QuadPart);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
std_info->AllocationSize.QuadPart =
|
|
|
|
|
nfs41_fcb->StandardInfo.AllocationSize.QuadPart;
|
|
|
|
|
}
|
|
|
|
|
if (nfs41_fcb->StandardInfo.EndOfFile.QuadPart >
|
|
|
|
|
std_info->EndOfFile.QuadPart) {
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_FILE_QUERY
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgP("Old EndOfFile is bigger: saving %x\n",
|
|
|
|
|
nfs41_fcb->StandardInfo.EndOfFile);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
std_info->EndOfFile.QuadPart =
|
|
|
|
|
nfs41_fcb->StandardInfo.EndOfFile.QuadPart;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
if (nfs41_fcb->StandardInfo.DeletePending)
|
|
|
|
|
DeletePending = TRUE;
|
|
|
|
|
RtlCopyMemory(&nfs41_fcb->StandardInfo, RxContext->Info.Buffer,
|
|
|
|
|
sizeof(nfs41_fcb->StandardInfo));
|
|
|
|
|
nfs41_fcb->StandardInfo.DeletePending = DeletePending;
|
|
|
|
|
nfs41_fcb->Flags |= FCB_STANDARD_INFO_CACHED;
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_FILE_QUERY
|
2010-10-11 14:59:26 -04:00
|
|
|
print_std_info(1, &nfs41_fcb->StandardInfo);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
status = map_queryfile_error(entry->status);
|
|
|
|
|
}
|
|
|
|
|
RxFreePool(entry);
|
|
|
|
|
out:
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
t2 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
InterlockedIncrement(&getattr.tops);
|
|
|
|
|
InterlockedAdd64(&getattr.ticks, t2.QuadPart - t1.QuadPart);
|
|
|
|
|
#ifdef ENABLE_INDV_TIMINGS
|
|
|
|
|
DbgP("nfs41_QueryFileInformation delta = %d op=%d sum=%d\n",
|
|
|
|
|
t2.QuadPart - t1.QuadPart, getattr.tops, getattr.ticks);
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_FILE_QUERY
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS map_setfile_error(
|
|
|
|
|
DWORD error)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
switch (error) {
|
|
|
|
|
case NO_ERROR: return STATUS_SUCCESS;
|
|
|
|
|
case ERROR_NOT_EMPTY: return STATUS_DIRECTORY_NOT_EMPTY;
|
|
|
|
|
case ERROR_FILE_EXISTS: return STATUS_OBJECT_NAME_COLLISION;
|
|
|
|
|
case ERROR_FILE_NOT_FOUND: return STATUS_OBJECT_NAME_NOT_FOUND;
|
|
|
|
|
case ERROR_PATH_NOT_FOUND: return STATUS_OBJECT_PATH_NOT_FOUND;
|
|
|
|
|
case ERROR_ACCESS_DENIED: return STATUS_ACCESS_DENIED;
|
2010-09-23 12:59:26 -04:00
|
|
|
case ERROR_FILE_INVALID: return STATUS_FILE_INVALID;
|
2010-10-11 14:59:26 -04:00
|
|
|
case ERROR_NOT_SAME_DEVICE: return STATUS_NOT_SAME_DEVICE;
|
|
|
|
|
case ERROR_NOT_SUPPORTED: return STATUS_NOT_IMPLEMENTED;
|
|
|
|
|
case ERROR_NETWORK_ACCESS_DENIED: return STATUS_NETWORK_ACCESS_DENIED;
|
|
|
|
|
case ERROR_NETNAME_DELETED: return STATUS_NETWORK_NAME_DELETED;
|
|
|
|
|
case ERROR_BUFFER_OVERFLOW: return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
default:
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("failed to map windows error %d to NTSTATUS; "
|
2010-10-11 14:59:26 -04:00
|
|
|
"defaulting to STATUS_INVALID_PARAMETER\n", error);
|
|
|
|
|
case ERROR_INVALID_PARAMETER: return STATUS_INVALID_PARAMETER;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_SetFileInformation(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_INVALID_PARAMETER;
|
|
|
|
|
nfs41_updowncall_entry *entry;
|
|
|
|
|
FILE_INFORMATION_CLASS InfoClass = RxContext->Info.FileInformationClass;
|
2011-12-21 15:53:17 -05:00
|
|
|
FILE_RENAME_INFORMATION rinfo;
|
2010-10-11 14:59:26 -04:00
|
|
|
PUNICODE_STRING FileName = GET_ALREADY_PREFIXED_NAME_FROM_CONTEXT(RxContext);
|
|
|
|
|
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
|
2010-10-11 14:59:26 -04:00
|
|
|
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
|
2010-11-05 20:08:55 -04:00
|
|
|
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_FCB nfs41_fcb = NFS41GetFcbExtension(RxContext->pFcb);
|
|
|
|
|
__notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
LARGE_INTEGER t1, t2;
|
|
|
|
|
t1 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_FILE_SET
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
2011-12-21 15:53:17 -05:00
|
|
|
print_debug_filedirquery_header(RxContext);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-10-04 10:57:06 -04:00
|
|
|
|
|
|
|
|
if (pVNetRootContext->read_only) {
|
|
|
|
|
DbgP("Read-only mount\n");
|
|
|
|
|
status = STATUS_ACCESS_DENIED;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-27 12:01:24 -04:00
|
|
|
/* http://msdn.microsoft.com/en-us/library/ff469355(v=PROT.10).aspx
|
|
|
|
|
* http://msdn.microsoft.com/en-us/library/ff469424(v=PROT.10).aspx
|
|
|
|
|
* If Open.GrantedAccess does not contain FILE_WRITE_DATA, the operation
|
|
|
|
|
* MUST be failed with STATUS_ACCESS_DENIED.
|
|
|
|
|
*/
|
|
|
|
|
if (InfoClass == FileAllocationInformation ||
|
|
|
|
|
InfoClass == FileEndOfFileInformation) {
|
|
|
|
|
if (!(SrvOpen->DesiredAccess & FILE_WRITE_DATA)) {
|
|
|
|
|
status = STATUS_ACCESS_DENIED;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
switch (InfoClass) {
|
|
|
|
|
case FileRenameInformation:
|
|
|
|
|
{
|
|
|
|
|
PFILE_RENAME_INFORMATION rinfo =
|
|
|
|
|
(PFILE_RENAME_INFORMATION)RxContext->Info.Buffer;
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_FILE_SET
|
2010-11-05 14:04:39 -04:00
|
|
|
UNICODE_STRING dst = { (USHORT)rinfo->FileNameLength,
|
|
|
|
|
(USHORT)rinfo->FileNameLength, rinfo->FileName };
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("Attempting to rename to '%wZ'\n", &dst);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
if (rinfo->RootDirectory) {
|
|
|
|
|
status = STATUS_NOT_SUPPORTED;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
nfs41_fcb->Flags = 0;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case FileLinkInformation:
|
|
|
|
|
{
|
|
|
|
|
PFILE_LINK_INFORMATION linfo =
|
|
|
|
|
(PFILE_LINK_INFORMATION)RxContext->Info.Buffer;
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_FILE_SET
|
2010-11-05 14:04:39 -04:00
|
|
|
UNICODE_STRING dst = { (USHORT)linfo->FileNameLength,
|
|
|
|
|
(USHORT)linfo->FileNameLength, linfo->FileName };
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("Attempting to add link as '%wZ'\n", &dst);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
if (linfo->RootDirectory) {
|
|
|
|
|
status = STATUS_NOT_SUPPORTED;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
nfs41_fcb->Flags = 0;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case FileDispositionInformation:
|
|
|
|
|
{
|
|
|
|
|
PFILE_DISPOSITION_INFORMATION dinfo =
|
|
|
|
|
(PFILE_DISPOSITION_INFORMATION)RxContext->Info.Buffer;
|
|
|
|
|
if (dinfo->DeleteFile) {
|
|
|
|
|
// we can delete directories right away
|
2010-10-12 09:59:34 -04:00
|
|
|
if (nfs41_fcb->StandardInfo.Directory)
|
|
|
|
|
break;
|
2010-10-11 14:59:26 -04:00
|
|
|
nfs41_fcb->Flags = 0;
|
|
|
|
|
nfs41_fcb->StandardInfo.DeletePending = TRUE;
|
2010-10-12 09:59:34 -04:00
|
|
|
if (RxContext->pFcb->OpenCount > 1) {
|
2010-10-11 14:59:26 -04:00
|
|
|
rinfo.ReplaceIfExists = 0;
|
|
|
|
|
rinfo.RootDirectory = INVALID_HANDLE_VALUE;
|
|
|
|
|
rinfo.FileNameLength = 0;
|
|
|
|
|
rinfo.FileName[0] = L'\0';
|
|
|
|
|
InfoClass = FileRenameInformation;
|
|
|
|
|
nfs41_fcb->Renamed = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
case FileBasicInformation:
|
|
|
|
|
case FileAllocationInformation:
|
|
|
|
|
nfs41_fcb->Flags = 0;
|
|
|
|
|
break;
|
|
|
|
|
case FileEndOfFileInformation:
|
|
|
|
|
{
|
|
|
|
|
PFILE_END_OF_FILE_INFORMATION info =
|
|
|
|
|
(PFILE_END_OF_FILE_INFORMATION)RxContext->Info.Buffer;
|
|
|
|
|
nfs41_fcb->StandardInfo.AllocationSize =
|
|
|
|
|
nfs41_fcb->StandardInfo.EndOfFile = info->EndOfFile;
|
|
|
|
|
nfs41_fcb->Flags = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("unknown set_file information class %d\n", InfoClass);
|
2010-10-11 14:59:26 -04:00
|
|
|
status = STATUS_NOT_SUPPORTED;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-13 15:28:48 -04:00
|
|
|
status = nfs41_UpcallCreate(NFS41_FILE_SET, &nfs41_fobx->sec_ctx,
|
|
|
|
|
pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
|
2012-02-13 16:08:21 -05:00
|
|
|
pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (status)
|
|
|
|
|
goto out;
|
|
|
|
|
entry->u.SetFile.filename = FileName;
|
|
|
|
|
entry->u.SetFile.InfoClass = InfoClass;
|
2011-06-27 12:01:24 -04:00
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
if (RxContext->Info.FileInformationClass == FileDispositionInformation &&
|
2011-12-21 15:53:17 -05:00
|
|
|
InfoClass == FileRenameInformation) {
|
2010-10-11 14:59:26 -04:00
|
|
|
entry->u.SetFile.buf = &rinfo;
|
|
|
|
|
entry->u.SetFile.buf_len = sizeof(rinfo);
|
|
|
|
|
} else {
|
|
|
|
|
entry->u.SetFile.buf = RxContext->Info.Buffer;
|
|
|
|
|
entry->u.SetFile.buf_len = RxContext->Info.Length;
|
|
|
|
|
}
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
InterlockedIncrement(&setattr.sops);
|
|
|
|
|
InterlockedAdd64(&setattr.size, entry->u.SetFile.buf_len);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
if (nfs41_UpcallWaitForReply(entry) != STATUS_SUCCESS) {
|
|
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
status = map_setfile_error(entry->status);
|
2012-02-08 18:24:19 -05:00
|
|
|
if (!status) {
|
|
|
|
|
if (!nfs41_fobx->deleg_type && entry->u.SetFile.ChangeTime &&
|
|
|
|
|
(SrvOpen->DesiredAccess &
|
|
|
|
|
(FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA)))
|
|
|
|
|
nfs41_update_srvopen_list(SrvOpen, entry->u.SetFile.ChangeTime);
|
|
|
|
|
nfs41_fcb->changeattr = entry->u.SetFile.ChangeTime;
|
|
|
|
|
}
|
2010-10-11 14:59:26 -04:00
|
|
|
RxFreePool(entry);
|
|
|
|
|
out:
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
t2 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
InterlockedIncrement(&setattr.tops);
|
|
|
|
|
InterlockedAdd64(&setattr.ticks, t2.QuadPart - t1.QuadPart);
|
|
|
|
|
#ifdef ENABLE_INDV_TIMINGS
|
|
|
|
|
DbgP("nfs41_SetFileInformation delta = %d op=%d sum=%d\n",
|
|
|
|
|
t2.QuadPart - t1.QuadPart, setattr.tops, setattr.ticks);
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_FILE_SET
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_SetFileInformationAtCleanup(
|
|
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status;
|
|
|
|
|
DbgEn();
|
|
|
|
|
status = nfs41_SetFileInformation(RxContext);
|
|
|
|
|
DbgEx();
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_IsValidDirectory (
|
|
|
|
|
IN OUT PRX_CONTEXT RxContext,
|
|
|
|
|
IN PUNICODE_STRING DirectoryName)
|
|
|
|
|
{
|
2012-02-13 16:08:21 -05:00
|
|
|
return STATUS_SUCCESS;
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_ComputeNewBufferingState(
|
|
|
|
|
IN OUT PMRX_SRV_OPEN pSrvOpen,
|
2011-12-21 15:53:17 -05:00
|
|
|
IN PVOID pMRxContext,
|
|
|
|
|
OUT ULONG *pNewBufferingState)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
ULONG flag;
|
|
|
|
|
DbgEn();
|
|
|
|
|
flag = PtrToUlong(pMRxContext);
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("nfs41_ComputeNewBufferingState: pSrvOpen %p Flags %08x\n",
|
|
|
|
|
pSrvOpen, pSrvOpen->BufferingFlags);
|
2010-10-11 14:59:26 -04:00
|
|
|
switch(flag) {
|
|
|
|
|
case DISABLE_CACHING:
|
|
|
|
|
if (pSrvOpen->BufferingFlags &
|
|
|
|
|
(FCB_STATE_READBUFFERING_ENABLED | FCB_STATE_READCACHING_ENABLED))
|
|
|
|
|
pSrvOpen->BufferingFlags &=
|
2011-12-21 15:53:17 -05:00
|
|
|
~(FCB_STATE_READBUFFERING_ENABLED |
|
|
|
|
|
FCB_STATE_READCACHING_ENABLED);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (pSrvOpen->BufferingFlags &
|
|
|
|
|
(FCB_STATE_WRITECACHING_ENABLED | FCB_STATE_WRITEBUFFERING_ENABLED))
|
|
|
|
|
pSrvOpen->BufferingFlags &=
|
2011-12-21 15:53:17 -05:00
|
|
|
~(FCB_STATE_WRITECACHING_ENABLED |
|
|
|
|
|
FCB_STATE_WRITEBUFFERING_ENABLED);
|
2010-10-11 14:59:26 -04:00
|
|
|
pSrvOpen->BufferingFlags |= FCB_STATE_DISABLE_LOCAL_BUFFERING;
|
|
|
|
|
break;
|
|
|
|
|
case ENABLE_READ_CACHING:
|
2010-10-12 09:53:45 -04:00
|
|
|
pSrvOpen->BufferingFlags |=
|
2010-10-11 14:59:26 -04:00
|
|
|
(FCB_STATE_READBUFFERING_ENABLED | FCB_STATE_READCACHING_ENABLED);
|
|
|
|
|
break;
|
|
|
|
|
case ENABLE_WRITE_CACHING:
|
2010-10-12 09:53:45 -04:00
|
|
|
pSrvOpen->BufferingFlags |=
|
2010-10-11 14:59:26 -04:00
|
|
|
(FCB_STATE_WRITECACHING_ENABLED | FCB_STATE_WRITEBUFFERING_ENABLED);
|
|
|
|
|
break;
|
|
|
|
|
case ENABLE_READWRITE_CACHING:
|
|
|
|
|
pSrvOpen->BufferingFlags =
|
|
|
|
|
(FCB_STATE_READBUFFERING_ENABLED | FCB_STATE_READCACHING_ENABLED |
|
|
|
|
|
FCB_STATE_WRITECACHING_ENABLED | FCB_STATE_WRITEBUFFERING_ENABLED);
|
|
|
|
|
}
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("nfs41_ComputeNewBufferingState: new Flags %08x\n",
|
|
|
|
|
pSrvOpen->BufferingFlags);
|
2010-10-11 14:59:26 -04:00
|
|
|
*pNewBufferingState = pSrvOpen->BufferingFlags;
|
|
|
|
|
|
|
|
|
|
DbgEx();
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
void print_readwrite_args(
|
|
|
|
|
PRX_CONTEXT RxContext)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
|
|
|
|
|
|
|
|
|
|
print_debug_header(RxContext);
|
|
|
|
|
DbgP("Bytecount 0x%x Byteoffset 0x%x Buffer %p\n",
|
|
|
|
|
LowIoContext->ParamsFor.ReadWrite.ByteCount,
|
|
|
|
|
LowIoContext->ParamsFor.ReadWrite.ByteOffset,
|
|
|
|
|
LowIoContext->ParamsFor.ReadWrite.Buffer);
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
void enable_caching(
|
2012-02-08 18:24:19 -05:00
|
|
|
PMRX_SRV_OPEN SrvOpen,
|
|
|
|
|
PNFS41_FOBX nfs41_fobx,
|
|
|
|
|
ULONGLONG ChangeTime)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
ULONG flag = 0;
|
2012-02-08 18:24:19 -05:00
|
|
|
PLIST_ENTRY pEntry;
|
|
|
|
|
nfs41_srvopen_list_entry *cur;
|
|
|
|
|
BOOLEAN found = FALSE;
|
|
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
if (SrvOpen->DesiredAccess & FILE_READ_DATA)
|
|
|
|
|
flag = ENABLE_READ_CACHING;
|
|
|
|
|
if (SrvOpen->DesiredAccess & FILE_WRITE_DATA)
|
|
|
|
|
flag = ENABLE_WRITE_CACHING;
|
|
|
|
|
if ((SrvOpen->DesiredAccess & FILE_READ_DATA) &&
|
|
|
|
|
(SrvOpen->DesiredAccess & FILE_WRITE_DATA))
|
|
|
|
|
flag = ENABLE_READWRITE_CACHING;
|
|
|
|
|
|
|
|
|
|
print_caching_level(1, flag);
|
|
|
|
|
|
|
|
|
|
if (!flag)
|
|
|
|
|
return;
|
|
|
|
|
|
2012-01-20 15:01:11 -05:00
|
|
|
RxChangeBufferingState((PSRV_OPEN)SrvOpen, ULongToPtr(flag), 1);
|
2012-02-08 18:24:19 -05:00
|
|
|
|
|
|
|
|
ExAcquireFastMutex(&srvopenLock);
|
|
|
|
|
pEntry = openlist->head.Flink;
|
|
|
|
|
DbgP("enable_caching: Looking for srv_open=%p\n", SrvOpen);
|
|
|
|
|
while (!IsListEmpty(&openlist->head)) {
|
|
|
|
|
cur = (nfs41_srvopen_list_entry *)CONTAINING_RECORD(pEntry,
|
|
|
|
|
nfs41_srvopen_list_entry, next);
|
|
|
|
|
if (cur->srv_open == SrvOpen) {
|
|
|
|
|
DbgP("enable_caching: Found match\n");
|
|
|
|
|
cur->skip = FALSE;
|
|
|
|
|
found = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (pEntry->Flink == &openlist->head) {
|
|
|
|
|
DbgP("enable_caching: reached end of the list\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
pEntry = pEntry->Flink;
|
|
|
|
|
}
|
|
|
|
|
if (!found && nfs41_fobx->deleg_type) {
|
|
|
|
|
nfs41_srvopen_list_entry *oentry;
|
|
|
|
|
DbgP("enable_caching: delegation recalled: srv_open=%p\n", SrvOpen);
|
|
|
|
|
oentry = RxAllocatePoolWithTag(NonPagedPool,
|
|
|
|
|
sizeof(nfs41_srvopen_list_entry), NFS41_MM_POOLTAG);
|
|
|
|
|
if (oentry == NULL) return;
|
|
|
|
|
oentry->srv_open = SrvOpen;
|
|
|
|
|
oentry->nfs41_fobx = nfs41_fobx;
|
|
|
|
|
oentry->ChangeTime = ChangeTime;
|
|
|
|
|
oentry->skip = FALSE;
|
|
|
|
|
InsertTailList(&openlist->head, &oentry->next);
|
|
|
|
|
nfs41_fobx->deleg_type = 0;
|
|
|
|
|
}
|
|
|
|
|
ExReleaseFastMutex(&srvopenLock);
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS map_readwrite_errors(
|
|
|
|
|
DWORD status)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
switch (status) {
|
|
|
|
|
case ERROR_ACCESS_DENIED: return STATUS_ACCESS_DENIED;
|
|
|
|
|
case ERROR_HANDLE_EOF: return STATUS_END_OF_FILE;
|
2010-11-30 13:10:30 -05:00
|
|
|
case ERROR_FILE_INVALID: return STATUS_FILE_INVALID;
|
2010-10-11 14:59:26 -04:00
|
|
|
case ERROR_INVALID_PARAMETER: return STATUS_INVALID_PARAMETER;
|
|
|
|
|
case ERROR_LOCK_VIOLATION: return STATUS_FILE_LOCK_CONFLICT;
|
|
|
|
|
case ERROR_NETWORK_ACCESS_DENIED: return STATUS_NETWORK_ACCESS_DENIED;
|
|
|
|
|
case ERROR_NETNAME_DELETED: return STATUS_NETWORK_NAME_DELETED;
|
|
|
|
|
default:
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("failed to map windows error %d to NTSTATUS; "
|
2010-10-11 14:59:26 -04:00
|
|
|
"defaulting to STATUS_NET_WRITE_FAULT\n", status);
|
|
|
|
|
case ERROR_NET_WRITE_FAULT: return STATUS_NET_WRITE_FAULT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_Read(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
nfs41_updowncall_entry *entry;
|
2011-12-21 15:53:17 -05:00
|
|
|
BOOLEAN async = FALSE;
|
2010-10-11 14:59:26 -04:00
|
|
|
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
|
|
|
|
|
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
|
2010-10-11 14:59:26 -04:00
|
|
|
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
|
2010-11-05 20:08:55 -04:00
|
|
|
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_FCB nfs41_fcb = NFS41GetFcbExtension(RxContext->pFcb);
|
|
|
|
|
__notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
LARGE_INTEGER t1, t2;
|
|
|
|
|
t1 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_READ
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
|
|
|
|
print_readwrite_args(RxContext);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2011-04-13 15:28:48 -04:00
|
|
|
status = nfs41_UpcallCreate(NFS41_READ, &nfs41_fobx->sec_ctx,
|
|
|
|
|
pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
|
2012-02-13 16:08:21 -05:00
|
|
|
pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (status)
|
|
|
|
|
goto out;
|
|
|
|
|
entry->u.ReadWrite.MdlAddress = LowIoContext->ParamsFor.ReadWrite.Buffer;
|
|
|
|
|
entry->u.ReadWrite.len = LowIoContext->ParamsFor.ReadWrite.ByteCount;
|
|
|
|
|
entry->u.ReadWrite.offset = LowIoContext->ParamsFor.ReadWrite.ByteOffset;
|
2011-12-21 15:53:17 -05:00
|
|
|
if (FlagOn(RxContext->CurrentIrpSp->FileObject->Flags,
|
|
|
|
|
FO_SYNCHRONOUS_IO) == FALSE) {
|
2010-10-11 14:59:26 -04:00
|
|
|
entry->u.ReadWrite.rxcontext = RxContext;
|
|
|
|
|
async = entry->async_op = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nfs41_UpcallWaitForReply(entry) != STATUS_SUCCESS) {
|
|
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (async) {
|
|
|
|
|
DbgP("This is asynchronous read, returning control back to the user\n");
|
|
|
|
|
status = STATUS_PENDING;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (entry->status == NO_ERROR) {
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
InterlockedIncrement(&read.sops);
|
|
|
|
|
InterlockedAdd64(&read.size, entry->u.ReadWrite.len);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
status = RxContext->CurrentIrp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
|
RxContext->IoStatusBlock.Information = entry->u.ReadWrite.len;
|
|
|
|
|
nfs41_fcb->Flags = 0;
|
|
|
|
|
|
2012-02-08 18:24:19 -05:00
|
|
|
if ((!BooleanFlagOn(LowIoContext->ParamsFor.ReadWrite.Flags,
|
2010-10-11 14:59:26 -04:00
|
|
|
LOWIO_READWRITEFLAG_PAGING_IO) &&
|
|
|
|
|
(SrvOpen->DesiredAccess & FILE_READ_DATA) &&
|
2011-12-08 17:47:34 -05:00
|
|
|
!pVNetRootContext->nocache &&
|
2010-10-11 14:59:26 -04:00
|
|
|
!(SrvOpen->BufferingFlags &
|
2011-12-21 15:53:17 -05:00
|
|
|
(FCB_STATE_READBUFFERING_ENABLED |
|
2012-02-08 18:24:19 -05:00
|
|
|
FCB_STATE_READCACHING_ENABLED)))) {
|
|
|
|
|
enable_caching(SrvOpen, nfs41_fobx, nfs41_fcb->changeattr);
|
|
|
|
|
}
|
2010-10-11 14:59:26 -04:00
|
|
|
} else {
|
|
|
|
|
status = map_readwrite_errors(entry->status);
|
|
|
|
|
RxContext->CurrentIrp->IoStatus.Status = status;
|
|
|
|
|
RxContext->IoStatusBlock.Information = 0;
|
|
|
|
|
}
|
|
|
|
|
RxFreePool(entry);
|
|
|
|
|
out:
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
t2 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
InterlockedIncrement(&read.tops);
|
|
|
|
|
InterlockedAdd64(&read.ticks, t2.QuadPart - t1.QuadPart);
|
|
|
|
|
#ifdef ENABLE_INDV_TIMINGS
|
|
|
|
|
DbgP("nfs41_Read delta = %d op=%d sum=%d\n", t2.QuadPart - t1.QuadPart,
|
|
|
|
|
read.tops, read.ticks);
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_READ
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_Write(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
nfs41_updowncall_entry *entry;
|
2011-12-21 15:53:17 -05:00
|
|
|
BOOLEAN async = FALSE;
|
2010-10-11 14:59:26 -04:00
|
|
|
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
|
|
|
|
|
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
|
2010-10-11 14:59:26 -04:00
|
|
|
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
|
2010-11-05 20:08:55 -04:00
|
|
|
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_FCB nfs41_fcb = NFS41GetFcbExtension(RxContext->pFcb);
|
|
|
|
|
__notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
LARGE_INTEGER t1, t2;
|
|
|
|
|
t1 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_WRITE
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
|
|
|
|
print_readwrite_args(RxContext);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2011-10-04 10:57:06 -04:00
|
|
|
if (pVNetRootContext->read_only) {
|
|
|
|
|
DbgP("Read-only mount\n");
|
|
|
|
|
status = STATUS_ACCESS_DENIED;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-13 15:28:48 -04:00
|
|
|
status = nfs41_UpcallCreate(NFS41_WRITE, &nfs41_fobx->sec_ctx,
|
|
|
|
|
pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
|
2012-02-13 16:08:21 -05:00
|
|
|
pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (status)
|
|
|
|
|
goto out;
|
|
|
|
|
entry->u.ReadWrite.MdlAddress = LowIoContext->ParamsFor.ReadWrite.Buffer;
|
|
|
|
|
entry->u.ReadWrite.len = LowIoContext->ParamsFor.ReadWrite.ByteCount;
|
|
|
|
|
entry->u.ReadWrite.offset = LowIoContext->ParamsFor.ReadWrite.ByteOffset;
|
2010-11-05 20:08:55 -04:00
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
if (FlagOn(RxContext->CurrentIrpSp->FileObject->Flags,
|
|
|
|
|
FO_SYNCHRONOUS_IO) == FALSE) {
|
2010-10-11 14:59:26 -04:00
|
|
|
entry->u.ReadWrite.rxcontext = RxContext;
|
|
|
|
|
async = entry->async_op = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nfs41_UpcallWaitForReply(entry) != STATUS_SUCCESS) {
|
|
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (async) {
|
|
|
|
|
DbgP("This is asynchronous write, returning control back to the user\n");
|
|
|
|
|
status = STATUS_PENDING;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (entry->status == NO_ERROR) {
|
|
|
|
|
//update cached file attributes
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
InterlockedIncrement(&write.sops);
|
|
|
|
|
InterlockedAdd64(&write.size, entry->u.ReadWrite.len);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
nfs41_fcb->StandardInfo.EndOfFile.QuadPart = entry->u.ReadWrite.len +
|
|
|
|
|
entry->u.ReadWrite.offset;
|
|
|
|
|
status = RxContext->CurrentIrp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
|
RxContext->IoStatusBlock.Information = entry->u.ReadWrite.len;
|
|
|
|
|
nfs41_fcb->Flags = 0;
|
2012-02-08 18:24:19 -05:00
|
|
|
nfs41_fcb->changeattr = entry->u.ReadWrite.ChangeTime;
|
2012-01-20 15:01:11 -05:00
|
|
|
|
|
|
|
|
//re-enable write buffering
|
2012-02-08 18:24:19 -05:00
|
|
|
if ((!BooleanFlagOn(LowIoContext->ParamsFor.ReadWrite.Flags,
|
2010-10-11 14:59:26 -04:00
|
|
|
LOWIO_READWRITEFLAG_PAGING_IO) &&
|
2012-02-08 18:24:19 -05:00
|
|
|
(SrvOpen->DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA)) &&
|
2011-12-07 18:10:09 -05:00
|
|
|
!pVNetRootContext->write_thru &&
|
2011-12-08 17:47:34 -05:00
|
|
|
!pVNetRootContext->nocache &&
|
2010-10-11 14:59:26 -04:00
|
|
|
!(SrvOpen->BufferingFlags &
|
2011-12-21 15:53:17 -05:00
|
|
|
(FCB_STATE_WRITEBUFFERING_ENABLED |
|
2012-02-08 18:24:19 -05:00
|
|
|
FCB_STATE_WRITECACHING_ENABLED)))) {
|
|
|
|
|
enable_caching(SrvOpen, nfs41_fobx, nfs41_fcb->changeattr);
|
|
|
|
|
} else if (!nfs41_fobx->deleg_type)
|
|
|
|
|
nfs41_update_srvopen_list(SrvOpen, entry->u.ReadWrite.ChangeTime);
|
|
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
} else {
|
|
|
|
|
status = map_readwrite_errors(entry->status);
|
|
|
|
|
RxContext->CurrentIrp->IoStatus.Status = status;
|
|
|
|
|
RxContext->IoStatusBlock.Information = 0;
|
|
|
|
|
}
|
|
|
|
|
RxFreePool(entry);
|
|
|
|
|
out:
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
t2 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
InterlockedIncrement(&write.tops);
|
|
|
|
|
InterlockedAdd64(&write.ticks, t2.QuadPart - t1.QuadPart);
|
|
|
|
|
#ifdef ENABLE_INDV_TIMINGS
|
|
|
|
|
DbgP("nfs41_Write delta = %d op=%d sum=%d\n", t2.QuadPart - t1.QuadPart,
|
|
|
|
|
write.tops, write.ticks);
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_WRITE
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_IsLockRealizable(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN OUT PMRX_FCB pFcb,
|
|
|
|
|
IN PLARGE_INTEGER ByteOffset,
|
|
|
|
|
IN PLARGE_INTEGER Length,
|
|
|
|
|
IN ULONG LowIoLockFlags)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_LOCK
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
|
|
|
|
DbgP("offset 0x%llx, length 0x%llx, exclusive=%u, blocking=%u\n",
|
|
|
|
|
ByteOffset->QuadPart,Length->QuadPart,
|
|
|
|
|
BooleanFlagOn(LowIoLockFlags, SL_EXCLUSIVE_LOCK),
|
|
|
|
|
!BooleanFlagOn(LowIoLockFlags, SL_FAIL_IMMEDIATELY));
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2011-06-13 12:02:59 -04:00
|
|
|
|
|
|
|
|
/* NFS lock operations with length=0 MUST fail with NFS4ERR_INVAL */
|
|
|
|
|
if (Length->QuadPart == 0)
|
|
|
|
|
status = STATUS_NOT_SUPPORTED;
|
|
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_LOCK
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS map_lock_errors(
|
|
|
|
|
DWORD status)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
switch (status) {
|
|
|
|
|
case NO_ERROR: return STATUS_SUCCESS;
|
|
|
|
|
case ERROR_NETNAME_DELETED: return STATUS_NETWORK_NAME_DELETED;
|
|
|
|
|
case ERROR_LOCK_FAILED: return STATUS_LOCK_NOT_GRANTED;
|
|
|
|
|
case ERROR_NOT_LOCKED: return STATUS_RANGE_NOT_LOCKED;
|
|
|
|
|
case ERROR_ATOMIC_LOCKS_NOT_SUPPORTED: return STATUS_UNSUCCESSFUL;
|
|
|
|
|
case ERROR_OUTOFMEMORY: return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
case ERROR_SHARING_VIOLATION: return STATUS_SHARING_VIOLATION;
|
2010-11-30 13:10:30 -05:00
|
|
|
case ERROR_FILE_INVALID: return STATUS_FILE_INVALID;
|
2010-10-11 14:59:26 -04:00
|
|
|
/* if we return ERROR_INVALID_PARAMETER, Windows translates that to
|
|
|
|
|
* success!! */
|
|
|
|
|
case ERROR_INVALID_PARAMETER: return STATUS_LOCK_NOT_GRANTED;
|
|
|
|
|
default:
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("failed to map windows error %d to NTSTATUS; "
|
2010-10-11 14:59:26 -04:00
|
|
|
"defaulting to STATUS_INVALID_NETWORK_RESPONSE\n", status);
|
|
|
|
|
case ERROR_BAD_NET_RESP: return STATUS_INVALID_NETWORK_RESPONSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
void print_lock_args(
|
|
|
|
|
PRX_CONTEXT RxContext)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
|
|
|
|
|
const ULONG flags = LowIoContext->ParamsFor.Locks.Flags;
|
|
|
|
|
print_debug_header(RxContext);
|
|
|
|
|
DbgP("offset 0x%llx, length 0x%llx, exclusive=%u, blocking=%u\n",
|
|
|
|
|
LowIoContext->ParamsFor.Locks.ByteOffset,
|
|
|
|
|
LowIoContext->ParamsFor.Locks.Length,
|
|
|
|
|
BooleanFlagOn(flags, SL_EXCLUSIVE_LOCK),
|
|
|
|
|
!BooleanFlagOn(flags, SL_FAIL_IMMEDIATELY));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* use exponential backoff between polls for blocking locks */
|
|
|
|
|
#define MSEC_TO_RELATIVE_WAIT (-10000)
|
|
|
|
|
#define MIN_LOCK_POLL_WAIT (500 * MSEC_TO_RELATIVE_WAIT) /* 500ms */
|
|
|
|
|
#define MAX_LOCK_POLL_WAIT (30000 * MSEC_TO_RELATIVE_WAIT) /* 30s */
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
void denied_lock_backoff(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN OUT PLARGE_INTEGER delay)
|
|
|
|
|
{
|
|
|
|
|
if (delay->QuadPart == 0)
|
|
|
|
|
delay->QuadPart = MIN_LOCK_POLL_WAIT;
|
|
|
|
|
else
|
|
|
|
|
delay->QuadPart <<= 1;
|
|
|
|
|
|
|
|
|
|
if (delay->QuadPart < MAX_LOCK_POLL_WAIT)
|
|
|
|
|
delay->QuadPart = MAX_LOCK_POLL_WAIT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_Lock(
|
|
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
nfs41_updowncall_entry *entry;
|
|
|
|
|
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
|
2010-10-11 14:59:26 -04:00
|
|
|
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
|
2010-10-11 14:59:26 -04:00
|
|
|
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
|
|
|
|
|
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
2010-10-11 14:59:26 -04:00
|
|
|
const ULONG flags = LowIoContext->ParamsFor.Locks.Flags;
|
|
|
|
|
LARGE_INTEGER poll_delay = {0};
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
LARGE_INTEGER t1, t2;
|
|
|
|
|
t1 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_LOCK
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
|
|
|
|
print_lock_args(RxContext);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
/* RxReleaseFcbResourceForThreadInMRx(RxContext, RxContext->pFcb,
|
|
|
|
|
LowIoContext->ResourceThreadId); */
|
|
|
|
|
|
2011-04-13 15:28:48 -04:00
|
|
|
status = nfs41_UpcallCreate(NFS41_LOCK, &nfs41_fobx->sec_ctx,
|
|
|
|
|
pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
|
2012-02-13 16:08:21 -05:00
|
|
|
pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (status)
|
|
|
|
|
goto out;
|
|
|
|
|
entry->u.Lock.offset = LowIoContext->ParamsFor.Locks.ByteOffset;
|
|
|
|
|
entry->u.Lock.length = LowIoContext->ParamsFor.Locks.Length;
|
|
|
|
|
entry->u.Lock.exclusive = BooleanFlagOn(flags, SL_EXCLUSIVE_LOCK);
|
|
|
|
|
entry->u.Lock.blocking = !BooleanFlagOn(flags, SL_FAIL_IMMEDIATELY);
|
|
|
|
|
|
|
|
|
|
retry_upcall:
|
|
|
|
|
if (nfs41_UpcallWaitForReply(entry) != STATUS_SUCCESS) {
|
|
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* blocking locks keep trying until it succeeds */
|
|
|
|
|
if (entry->status == ERROR_LOCK_FAILED && entry->u.Lock.blocking) {
|
|
|
|
|
denied_lock_backoff(&poll_delay);
|
|
|
|
|
DbgP("returned ERROR_LOCK_FAILED; retrying in %llums\n",
|
|
|
|
|
poll_delay.QuadPart / MSEC_TO_RELATIVE_WAIT);
|
|
|
|
|
KeDelayExecutionThread(KernelMode, FALSE, &poll_delay);
|
|
|
|
|
entry->state = NFS41_WAITING_FOR_UPCALL;
|
|
|
|
|
goto retry_upcall;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
status = map_lock_errors(entry->status);
|
|
|
|
|
RxContext->CurrentIrp->IoStatus.Status = status;
|
|
|
|
|
|
|
|
|
|
RxFreePool(entry);
|
|
|
|
|
out:
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
t2 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
InterlockedIncrement(&lock.tops);
|
|
|
|
|
InterlockedAdd64(&lock.ticks, t2.QuadPart - t1.QuadPart);
|
|
|
|
|
#ifdef ENABLE_INDV_TIMINGS
|
|
|
|
|
DbgP("nfs41_Lock delta = %d op=%d sum=%d\n", t2.QuadPart - t1.QuadPart,
|
|
|
|
|
lock.tops, lock.ticks);
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_LOCK
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
void print_unlock_args(
|
|
|
|
|
PRX_CONTEXT RxContext)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
|
|
|
|
|
print_debug_header(RxContext);
|
|
|
|
|
if (LowIoContext->Operation == LOWIO_OP_UNLOCK_MULTIPLE) {
|
|
|
|
|
PLOWIO_LOCK_LIST lock = LowIoContext->ParamsFor.Locks.LockList;
|
|
|
|
|
DbgP("LOWIO_OP_UNLOCK_MULTIPLE:");
|
|
|
|
|
while (lock) {
|
|
|
|
|
DbgP(" (offset=%llu, length=%llu)", lock->ByteOffset, lock->Length);
|
|
|
|
|
lock = lock->Next;
|
|
|
|
|
}
|
|
|
|
|
DbgP("\n");
|
|
|
|
|
} else {
|
|
|
|
|
DbgP("LOWIO_OP_UNLOCK: offset=%llu, length=%llu\n",
|
|
|
|
|
LowIoContext->ParamsFor.Locks.ByteOffset,
|
|
|
|
|
LowIoContext->ParamsFor.Locks.Length);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
__inline ULONG unlock_list_count(
|
|
|
|
|
PLOWIO_LOCK_LIST lock)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
ULONG count = 0;
|
|
|
|
|
while (lock) {
|
|
|
|
|
count++;
|
|
|
|
|
lock = lock->Next;
|
|
|
|
|
}
|
|
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_Unlock(
|
|
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
nfs41_updowncall_entry *entry;
|
|
|
|
|
PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_FOBX nfs41_fobx = NFS41GetFobxExtension(RxContext->pFobx);
|
2010-10-11 14:59:26 -04:00
|
|
|
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
|
2010-10-11 14:59:26 -04:00
|
|
|
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
|
2010-11-05 20:08:55 -04:00
|
|
|
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
LARGE_INTEGER t1, t2;
|
|
|
|
|
t1 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
#endif
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_LOCK
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEn();
|
|
|
|
|
print_lock_args(RxContext);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
/* RxReleaseFcbResourceForThreadInMRx(RxContext, RxContext->pFcb,
|
|
|
|
|
LowIoContext->ResourceThreadId); */
|
|
|
|
|
|
2011-04-13 15:28:48 -04:00
|
|
|
status = nfs41_UpcallCreate(NFS41_UNLOCK, &nfs41_fobx->sec_ctx,
|
|
|
|
|
pVNetRootContext->session, nfs41_fobx->nfs41_open_state,
|
2012-02-13 16:08:21 -05:00
|
|
|
pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
|
2010-10-11 14:59:26 -04:00
|
|
|
if (status)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
if (LowIoContext->Operation == LOWIO_OP_UNLOCK_MULTIPLE) {
|
|
|
|
|
entry->u.Unlock.count = unlock_list_count(
|
|
|
|
|
LowIoContext->ParamsFor.Locks.LockList);
|
|
|
|
|
RtlCopyMemory(&entry->u.Unlock.locks,
|
|
|
|
|
LowIoContext->ParamsFor.Locks.LockList,
|
|
|
|
|
sizeof(LOWIO_LOCK_LIST));
|
|
|
|
|
} else {
|
|
|
|
|
entry->u.Unlock.count = 1;
|
|
|
|
|
entry->u.Unlock.locks.ByteOffset =
|
|
|
|
|
LowIoContext->ParamsFor.Locks.ByteOffset;
|
|
|
|
|
entry->u.Unlock.locks.Length =
|
|
|
|
|
LowIoContext->ParamsFor.Locks.Length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nfs41_UpcallWaitForReply(entry) != STATUS_SUCCESS) {
|
|
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
status = map_lock_errors(entry->status);
|
|
|
|
|
RxContext->CurrentIrp->IoStatus.Status = status;
|
|
|
|
|
RxFreePool(entry);
|
|
|
|
|
out:
|
2011-09-06 18:01:17 -04:00
|
|
|
#ifdef ENABLE_TIMINGS
|
|
|
|
|
t2 = KeQueryPerformanceCounter(NULL);
|
|
|
|
|
InterlockedIncrement(&unlock.tops);
|
|
|
|
|
InterlockedAdd64(&unlock.ticks, t2.QuadPart - t1.QuadPart);
|
|
|
|
|
#ifdef ENABLE_INDV_TIMINGS
|
|
|
|
|
DbgP("nfs41_Unlock delta = %d op=%d sum=%d\n", t2.QuadPart - t1.QuadPart,
|
|
|
|
|
unlock.tops, unlock.ticks);
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_LOCK
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-10-11 14:59:26 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS map_symlink_errors(
|
|
|
|
|
NTSTATUS status)
|
2010-09-23 12:48:02 -04:00
|
|
|
{
|
|
|
|
|
switch (status) {
|
|
|
|
|
case NO_ERROR: return STATUS_SUCCESS;
|
|
|
|
|
case ERROR_INVALID_REPARSE_DATA: return STATUS_IO_REPARSE_DATA_INVALID;
|
|
|
|
|
case ERROR_NOT_A_REPARSE_POINT: return STATUS_NOT_A_REPARSE_POINT;
|
|
|
|
|
case ERROR_OUTOFMEMORY: return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
case ERROR_INSUFFICIENT_BUFFER: return STATUS_BUFFER_TOO_SMALL;
|
|
|
|
|
case STATUS_BUFFER_TOO_SMALL:
|
|
|
|
|
case ERROR_BUFFER_OVERFLOW: return STATUS_BUFFER_OVERFLOW;
|
|
|
|
|
default:
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("failed to map windows error %d to NTSTATUS; "
|
2010-09-23 12:48:02 -04:00
|
|
|
"defaulting to STATUS_INVALID_NETWORK_RESPONSE\n", status);
|
|
|
|
|
case ERROR_BAD_NET_RESP: return STATUS_INVALID_NETWORK_RESPONSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
void print_reparse_buffer(
|
|
|
|
|
PREPARSE_DATA_BUFFER Reparse)
|
2010-09-23 12:48:02 -04:00
|
|
|
{
|
|
|
|
|
UNICODE_STRING name;
|
|
|
|
|
DbgP("ReparseTag: %08X\n", Reparse->ReparseTag);
|
|
|
|
|
DbgP("ReparseDataLength: %8u\n", Reparse->ReparseDataLength);
|
|
|
|
|
DbgP("Reserved: %8u\n", Reparse->Reserved);
|
2011-12-21 15:53:17 -05:00
|
|
|
DbgP("SubstituteNameOffset: %8u\n",
|
|
|
|
|
Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset);
|
|
|
|
|
DbgP("SubstituteNameLength: %8u\n",
|
|
|
|
|
Reparse->SymbolicLinkReparseBuffer.SubstituteNameLength);
|
|
|
|
|
DbgP("PrintNameOffset: %8u\n",
|
|
|
|
|
Reparse->SymbolicLinkReparseBuffer.PrintNameOffset);
|
|
|
|
|
DbgP("PrintNameLength: %8u\n",
|
|
|
|
|
Reparse->SymbolicLinkReparseBuffer.PrintNameLength);
|
|
|
|
|
DbgP("Flags: %08X\n",
|
|
|
|
|
Reparse->SymbolicLinkReparseBuffer.Flags);
|
2010-09-23 12:48:02 -04:00
|
|
|
|
|
|
|
|
name.Buffer = &Reparse->SymbolicLinkReparseBuffer.PathBuffer[
|
|
|
|
|
Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)];
|
|
|
|
|
name.MaximumLength = name.Length =
|
|
|
|
|
Reparse->SymbolicLinkReparseBuffer.SubstituteNameLength;
|
|
|
|
|
DbgP("SubstituteName: %wZ\n", &name);
|
|
|
|
|
|
|
|
|
|
name.Buffer = &Reparse->SymbolicLinkReparseBuffer.PathBuffer[
|
|
|
|
|
Reparse->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR)];
|
|
|
|
|
name.MaximumLength = name.Length =
|
|
|
|
|
Reparse->SymbolicLinkReparseBuffer.PrintNameLength;
|
|
|
|
|
DbgP("PrintName: %wZ\n", &name);
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_SetReparsePoint(
|
2010-09-23 13:13:18 -04:00
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status;
|
2011-12-21 15:53:17 -05:00
|
|
|
UNICODE_STRING TargetName;
|
|
|
|
|
__notnull XXCTL_LOWIO_COMPONENT *FsCtl = &RxContext->LowIoContext.ParamsFor.FsCtl;
|
|
|
|
|
__notnull PREPARSE_DATA_BUFFER Reparse = (PREPARSE_DATA_BUFFER)FsCtl->pInputBuffer;
|
|
|
|
|
__notnull PNFS41_FOBX Fobx = NFS41GetFobxExtension(RxContext->pFobx);
|
|
|
|
|
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
|
|
|
|
|
__notnull PNFS41_V_NET_ROOT_EXTENSION VNetRoot =
|
|
|
|
|
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
|
|
|
|
|
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
|
2010-11-05 20:08:55 -04:00
|
|
|
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
2011-12-21 15:53:17 -05:00
|
|
|
nfs41_updowncall_entry *entry;
|
2010-09-23 13:13:18 -04:00
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_SYMLINK
|
2010-10-14 13:46:14 -04:00
|
|
|
DbgEn();
|
2010-09-23 13:13:18 -04:00
|
|
|
print_reparse_buffer(Reparse);
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-09-23 13:13:18 -04:00
|
|
|
|
|
|
|
|
if (Reparse->ReparseTag != IO_REPARSE_TAG_SYMLINK) {
|
|
|
|
|
status = STATUS_IO_REPARSE_TAG_MISMATCH;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TargetName.MaximumLength = TargetName.Length =
|
|
|
|
|
Reparse->SymbolicLinkReparseBuffer.PrintNameLength;
|
|
|
|
|
TargetName.Buffer = &Reparse->SymbolicLinkReparseBuffer.PathBuffer[
|
|
|
|
|
Reparse->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR)];
|
|
|
|
|
|
2011-04-13 15:28:48 -04:00
|
|
|
status = nfs41_UpcallCreate(NFS41_SYMLINK, &Fobx->sec_ctx,
|
|
|
|
|
VNetRoot->session, Fobx->nfs41_open_state,
|
2012-02-13 16:08:21 -05:00
|
|
|
pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
|
2010-09-23 13:13:18 -04:00
|
|
|
if (status)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
entry->u.Symlink.filename = SrvOpen->pAlreadyPrefixedName;
|
|
|
|
|
entry->u.Symlink.target = &TargetName;
|
|
|
|
|
entry->u.Symlink.set = TRUE;
|
|
|
|
|
|
|
|
|
|
if (nfs41_UpcallWaitForReply(entry) != STATUS_SUCCESS) {
|
|
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
status = map_symlink_errors(entry->status);
|
|
|
|
|
RxFreePool(entry);
|
|
|
|
|
out:
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_SYMLINK
|
2010-10-14 13:46:14 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-09-23 13:13:18 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_GetReparsePoint(
|
2010-09-23 12:48:02 -04:00
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS status;
|
2010-09-23 12:48:02 -04:00
|
|
|
UNICODE_STRING TargetName;
|
|
|
|
|
XXCTL_LOWIO_COMPONENT *FsCtl = &RxContext->LowIoContext.ParamsFor.FsCtl;
|
2011-12-21 15:53:17 -05:00
|
|
|
__notnull PNFS41_FOBX Fobx = NFS41GetFobxExtension(RxContext->pFobx);
|
|
|
|
|
__notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
|
|
|
|
|
__notnull PNFS41_V_NET_ROOT_EXTENSION VNetRoot =
|
|
|
|
|
NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
|
|
|
|
|
__notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
|
|
|
|
|
NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
|
2010-09-23 12:48:02 -04:00
|
|
|
nfs41_updowncall_entry *entry;
|
|
|
|
|
const USHORT HeaderLen = FIELD_OFFSET(REPARSE_DATA_BUFFER,
|
|
|
|
|
SymbolicLinkReparseBuffer.PathBuffer);
|
|
|
|
|
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_SYMLINK
|
2010-10-14 13:46:14 -04:00
|
|
|
DbgEn();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-11-04 09:57:43 -04:00
|
|
|
|
|
|
|
|
if (!BooleanFlagOn(RxContext->pFcb->Attributes,
|
|
|
|
|
FILE_ATTRIBUTE_REPARSE_POINT)) {
|
|
|
|
|
status = STATUS_NOT_A_REPARSE_POINT;
|
|
|
|
|
DbgP("FILE_ATTRIBUTE_REPARSE_POINT is not set!\n");
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-23 12:48:02 -04:00
|
|
|
if (FsCtl->OutputBufferLength < HeaderLen) {
|
|
|
|
|
RxContext->InformationToReturn = HeaderLen;
|
|
|
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TargetName.Buffer = (PWCH)((PBYTE)FsCtl->pOutputBuffer + HeaderLen);
|
2011-12-21 15:53:17 -05:00
|
|
|
TargetName.MaximumLength = (USHORT)min(FsCtl->OutputBufferLength -
|
|
|
|
|
HeaderLen, 0xFFFF);
|
2010-09-23 12:48:02 -04:00
|
|
|
|
2011-04-13 15:28:48 -04:00
|
|
|
status = nfs41_UpcallCreate(NFS41_SYMLINK, &Fobx->sec_ctx,
|
|
|
|
|
VNetRoot->session, Fobx->nfs41_open_state,
|
2012-02-13 16:08:21 -05:00
|
|
|
pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
|
2010-09-23 12:48:02 -04:00
|
|
|
if (status)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
entry->u.Symlink.filename = SrvOpen->pAlreadyPrefixedName;
|
|
|
|
|
entry->u.Symlink.target = &TargetName;
|
|
|
|
|
entry->u.Symlink.set = FALSE;
|
|
|
|
|
|
|
|
|
|
if (nfs41_UpcallWaitForReply(entry) != STATUS_SUCCESS) {
|
|
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
status = map_symlink_errors(entry->status);
|
|
|
|
|
if (status == STATUS_SUCCESS) {
|
|
|
|
|
/* fill in the output buffer */
|
2011-12-21 15:53:17 -05:00
|
|
|
PREPARSE_DATA_BUFFER Reparse = (PREPARSE_DATA_BUFFER)
|
|
|
|
|
FsCtl->pOutputBuffer;
|
2010-09-23 12:48:02 -04:00
|
|
|
Reparse->ReparseTag = IO_REPARSE_TAG_SYMLINK;
|
|
|
|
|
Reparse->ReparseDataLength = HeaderLen + TargetName.Length -
|
|
|
|
|
REPARSE_DATA_BUFFER_HEADER_SIZE;
|
|
|
|
|
Reparse->Reserved = 0;
|
|
|
|
|
Reparse->SymbolicLinkReparseBuffer.Flags = SYMLINK_FLAG_RELATIVE;
|
|
|
|
|
/* PrintName and SubstituteName point to the same string */
|
|
|
|
|
Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
|
2011-12-21 15:53:17 -05:00
|
|
|
Reparse->SymbolicLinkReparseBuffer.SubstituteNameLength =
|
|
|
|
|
TargetName.Length;
|
2010-09-23 12:48:02 -04:00
|
|
|
Reparse->SymbolicLinkReparseBuffer.PrintNameOffset = 0;
|
|
|
|
|
Reparse->SymbolicLinkReparseBuffer.PrintNameLength = TargetName.Length;
|
|
|
|
|
print_reparse_buffer(Reparse);
|
|
|
|
|
|
|
|
|
|
RxContext->IoStatusBlock.Information = HeaderLen + TargetName.Length;
|
|
|
|
|
} else if (status == STATUS_BUFFER_TOO_SMALL) {
|
|
|
|
|
RxContext->InformationToReturn = HeaderLen + TargetName.Length;
|
|
|
|
|
}
|
|
|
|
|
RxFreePool(entry);
|
|
|
|
|
out:
|
2012-02-13 16:08:21 -05:00
|
|
|
#ifdef DEBUG_SYMLINK
|
2010-10-14 13:46:14 -04:00
|
|
|
DbgEx();
|
2012-02-13 16:08:21 -05:00
|
|
|
#endif
|
2010-09-23 12:48:02 -04:00
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
NTSTATUS nfs41_FsCtl(
|
|
|
|
|
IN OUT PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
|
DbgEn();
|
2010-11-05 14:05:39 -04:00
|
|
|
print_debug_header(RxContext);
|
2010-09-23 12:48:02 -04:00
|
|
|
switch (RxContext->LowIoContext.ParamsFor.FsCtl.FsControlCode) {
|
2010-09-23 13:13:18 -04:00
|
|
|
case FSCTL_SET_REPARSE_POINT:
|
|
|
|
|
status = nfs41_SetReparsePoint(RxContext);
|
|
|
|
|
break;
|
|
|
|
|
|
2010-09-23 12:48:02 -04:00
|
|
|
case FSCTL_GET_REPARSE_POINT:
|
|
|
|
|
status = nfs41_GetReparsePoint(RxContext);
|
|
|
|
|
break;
|
2011-04-14 20:14:21 -04:00
|
|
|
default:
|
2011-12-21 15:53:17 -05:00
|
|
|
DbgP("FsControlCode: %d\n",
|
|
|
|
|
RxContext->LowIoContext.ParamsFor.FsCtl.FsControlCode);
|
2010-09-23 12:48:02 -04:00
|
|
|
}
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS nfs41_CompleteBufferingStateChangeRequest(
|
2010-10-11 14:59:26 -04:00
|
|
|
IN OUT PRX_CONTEXT RxContext,
|
2011-12-21 15:53:17 -05:00
|
|
|
IN OUT PMRX_SRV_OPEN SrvOpen,
|
|
|
|
|
IN PVOID pContext)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
|
DbgEn();
|
|
|
|
|
DbgEx();
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_FsdDispatch (
|
|
|
|
|
IN PDEVICE_OBJECT dev,
|
2011-12-21 15:53:17 -05:00
|
|
|
IN PIRP Irp)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
#ifdef DEBUG_FSDDISPATCH
|
|
|
|
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
|
|
|
|
|
#endif
|
|
|
|
|
NTSTATUS status;
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG_FSDDISPATCH
|
|
|
|
|
DbgEn();
|
|
|
|
|
DbgP("CURRENT IRP = %d.%d\n", IrpSp->MajorFunction, IrpSp->MinorFunction);
|
|
|
|
|
if(IrpSp->FileObject)
|
|
|
|
|
DbgP("FileOject %p Filename %wZ\n", IrpSp->FileObject,
|
|
|
|
|
&IrpSp->FileObject->FileName);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (dev != (PDEVICE_OBJECT)nfs41_dev) {
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("*** not ours ***\n");
|
2010-10-11 14:59:26 -04:00
|
|
|
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT );
|
|
|
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
status = RxFsdDispatch((PRDBSS_DEVICE_OBJECT)dev,Irp);
|
|
|
|
|
/* AGLO: 08/05/2009 - looks like RxFsdDispatch frees IrpSp */
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
#ifdef DEBUG_FSDDISPATCH
|
2011-12-21 15:53:17 -05:00
|
|
|
DbgP("IoStatus status = 0x%x info = 0x%x\n", Irp->IoStatus.Status,
|
|
|
|
|
Irp->IoStatus.Information);
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgEx();
|
|
|
|
|
#endif
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-22 15:49:16 -05:00
|
|
|
NTSTATUS nfs41_Unimplemented(
|
|
|
|
|
PRX_CONTEXT RxContext)
|
|
|
|
|
{
|
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS nfs41_AreFilesAliased(
|
|
|
|
|
PFCB a,
|
|
|
|
|
PFCB b)
|
|
|
|
|
{
|
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
NTSTATUS nfs41_init_ops()
|
|
|
|
|
{
|
|
|
|
|
DbgEn();
|
|
|
|
|
|
|
|
|
|
ZeroAndInitializeNodeType(&nfs41_ops, RDBSS_NTC_MINIRDR_DISPATCH,
|
|
|
|
|
sizeof(MINIRDR_DISPATCH));
|
|
|
|
|
|
|
|
|
|
nfs41_ops.MRxFlags = (RDBSS_MANAGE_NET_ROOT_EXTENSION |
|
|
|
|
|
RDBSS_MANAGE_V_NET_ROOT_EXTENSION |
|
|
|
|
|
RDBSS_MANAGE_FCB_EXTENSION |
|
|
|
|
|
RDBSS_MANAGE_FOBX_EXTENSION);
|
|
|
|
|
|
2011-04-20 12:36:02 -04:00
|
|
|
nfs41_ops.MRxSrvCallSize = 0; // srvcall extension is not handled in rdbss
|
2010-10-11 14:59:26 -04:00
|
|
|
nfs41_ops.MRxNetRootSize = sizeof(NFS41_NETROOT_EXTENSION);
|
|
|
|
|
nfs41_ops.MRxVNetRootSize = sizeof(NFS41_V_NET_ROOT_EXTENSION);
|
|
|
|
|
nfs41_ops.MRxFcbSize = sizeof(NFS41_FCB);
|
|
|
|
|
nfs41_ops.MRxFobxSize = sizeof(NFS41_FOBX);
|
|
|
|
|
|
|
|
|
|
// Mini redirector cancel routine ..
|
|
|
|
|
|
|
|
|
|
nfs41_ops.MRxCancel = NULL;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Mini redirector Start/Stop. Each mini-rdr can be started or stopped
|
|
|
|
|
// while the others continue to operate.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
nfs41_ops.MRxStart = nfs41_Start;
|
|
|
|
|
nfs41_ops.MRxStop = nfs41_Stop;
|
|
|
|
|
nfs41_ops.MRxDevFcbXXXControlFile = nfs41_DevFcbXXXControlFile;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Mini redirector name resolution.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
nfs41_ops.MRxCreateSrvCall = nfs41_CreateSrvCall;
|
|
|
|
|
nfs41_ops.MRxSrvCallWinnerNotify = nfs41_SrvCallWinnerNotify;
|
|
|
|
|
nfs41_ops.MRxCreateVNetRoot = nfs41_CreateVNetRoot;
|
|
|
|
|
nfs41_ops.MRxExtractNetRootName = nfs41_ExtractNetRootName;
|
|
|
|
|
nfs41_ops.MRxFinalizeSrvCall = nfs41_FinalizeSrvCall;
|
|
|
|
|
nfs41_ops.MRxFinalizeNetRoot = nfs41_FinalizeNetRoot;
|
|
|
|
|
nfs41_ops.MRxFinalizeVNetRoot = nfs41_FinalizeVNetRoot;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// File System Object Creation/Deletion.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
nfs41_ops.MRxCreate = nfs41_Create;
|
|
|
|
|
nfs41_ops.MRxCollapseOpen = nfs41_CollapseOpen;
|
|
|
|
|
nfs41_ops.MRxShouldTryToCollapseThisOpen = nfs41_ShouldTryToCollapseThisOpen;
|
|
|
|
|
nfs41_ops.MRxExtendForCache = nfs41_ExtendForCache;
|
|
|
|
|
nfs41_ops.MRxExtendForNonCache = nfs41_ExtendForCache;
|
|
|
|
|
nfs41_ops.MRxCloseSrvOpen = nfs41_CloseSrvOpen;
|
|
|
|
|
nfs41_ops.MRxFlush = nfs41_Flush;
|
|
|
|
|
nfs41_ops.MRxDeallocateForFcb = nfs41_DeallocateForFcb;
|
|
|
|
|
nfs41_ops.MRxDeallocateForFobx = nfs41_DeallocateForFobx;
|
|
|
|
|
nfs41_ops.MRxIsLockRealizable = nfs41_IsLockRealizable;
|
2011-12-21 15:53:17 -05:00
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
//
|
|
|
|
|
// File System Objects query/Set
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
nfs41_ops.MRxQueryDirectory = nfs41_QueryDirectory;
|
|
|
|
|
nfs41_ops.MRxQueryVolumeInfo = nfs41_QueryVolumeInformation;
|
|
|
|
|
nfs41_ops.MRxQueryEaInfo = nfs41_QueryEaInformation;
|
|
|
|
|
nfs41_ops.MRxSetEaInfo = nfs41_SetEaInformation;
|
|
|
|
|
nfs41_ops.MRxQuerySdInfo = nfs41_QuerySecurityInformation;
|
|
|
|
|
nfs41_ops.MRxSetSdInfo = nfs41_SetSecurityInformation;
|
|
|
|
|
nfs41_ops.MRxQueryFileInfo = nfs41_QueryFileInformation;
|
|
|
|
|
nfs41_ops.MRxSetFileInfo = nfs41_SetFileInformation;
|
2011-12-21 15:53:17 -05:00
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
//
|
|
|
|
|
// Buffering state change
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
nfs41_ops.MRxComputeNewBufferingState = nfs41_ComputeNewBufferingState;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// File System Object I/O
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
nfs41_ops.MRxLowIOSubmit[LOWIO_OP_READ] = nfs41_Read;
|
|
|
|
|
nfs41_ops.MRxLowIOSubmit[LOWIO_OP_WRITE] = nfs41_Write;
|
|
|
|
|
nfs41_ops.MRxLowIOSubmit[LOWIO_OP_SHAREDLOCK] = nfs41_Lock;
|
|
|
|
|
nfs41_ops.MRxLowIOSubmit[LOWIO_OP_EXCLUSIVELOCK] = nfs41_Lock;
|
|
|
|
|
nfs41_ops.MRxLowIOSubmit[LOWIO_OP_UNLOCK] = nfs41_Unlock;
|
|
|
|
|
nfs41_ops.MRxLowIOSubmit[LOWIO_OP_UNLOCK_MULTIPLE] = nfs41_Unlock;
|
|
|
|
|
nfs41_ops.MRxLowIOSubmit[LOWIO_OP_FSCTL] = nfs41_FsCtl;
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Miscellanous
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
nfs41_ops.MRxCompleteBufferingStateChangeRequest =
|
|
|
|
|
nfs41_CompleteBufferingStateChangeRequest;
|
|
|
|
|
nfs41_ops.MRxIsValidDirectory = nfs41_IsValidDirectory;
|
|
|
|
|
|
2011-12-22 15:49:16 -05:00
|
|
|
nfs41_ops.MRxTruncate = nfs41_Unimplemented;
|
|
|
|
|
nfs41_ops.MRxZeroExtend = nfs41_Unimplemented;
|
|
|
|
|
nfs41_ops.MRxAreFilesAliased = nfs41_AreFilesAliased;
|
|
|
|
|
nfs41_ops.MRxQueryQuotaInfo = nfs41_Unimplemented;
|
|
|
|
|
nfs41_ops.MRxSetQuotaInfo = nfs41_Unimplemented;
|
|
|
|
|
nfs41_ops.MRxSetVolumeInfo = nfs41_Unimplemented;
|
|
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
DbgR();
|
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-08 18:24:19 -05:00
|
|
|
#define RELATIVE(wait) (-(wait))
|
|
|
|
|
#define NANOSECONDS(nanos) (((signed __int64)(nanos)) / 100L)
|
|
|
|
|
#define MICROSECONDS(micros) (((signed __int64)(micros)) * NANOSECONDS(1000L))
|
|
|
|
|
#define MILLISECONDS(milli) (((signed __int64)(milli)) * MICROSECONDS(1000L))
|
|
|
|
|
#define SECONDS(seconds) (((signed __int64)(seconds)) * MILLISECONDS(1000L))
|
|
|
|
|
|
|
|
|
|
KSTART_ROUTINE srvopen_main;
|
|
|
|
|
VOID srvopen_main(PVOID ctx)
|
|
|
|
|
{
|
|
|
|
|
NTSTATUS status;
|
|
|
|
|
LARGE_INTEGER timeout;
|
|
|
|
|
|
|
|
|
|
DbgEn();
|
|
|
|
|
timeout.QuadPart = RELATIVE(SECONDS(30));
|
|
|
|
|
while(1) {
|
|
|
|
|
PLIST_ENTRY pEntry;
|
|
|
|
|
nfs41_srvopen_list_entry *cur;
|
|
|
|
|
status = KeDelayExecutionThread(KernelMode, TRUE, &timeout);
|
|
|
|
|
ExAcquireFastMutex(&srvopenLock);
|
|
|
|
|
pEntry = openlist->head.Flink;
|
|
|
|
|
while (!IsListEmpty(&openlist->head)) {
|
|
|
|
|
PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext;
|
|
|
|
|
PNFS41_NETROOT_EXTENSION pNetRootContext;
|
|
|
|
|
nfs41_updowncall_entry *entry;
|
|
|
|
|
FILE_BASIC_INFORMATION binfo;
|
|
|
|
|
PNFS41_FCB nfs41_fcb;
|
|
|
|
|
cur = (nfs41_srvopen_list_entry *)CONTAINING_RECORD(pEntry,
|
|
|
|
|
nfs41_srvopen_list_entry, next);
|
|
|
|
|
|
|
|
|
|
DbgP("srvopen_main: Checking attributes for srv_open=%p "
|
|
|
|
|
"change_time=%llu skipping=%d\n", cur->srv_open,
|
|
|
|
|
cur->ChangeTime, cur->skip);
|
|
|
|
|
if (cur->skip) goto out;
|
|
|
|
|
pVNetRootContext =
|
|
|
|
|
NFS41GetVNetRootExtension(cur->srv_open->pVNetRoot);
|
|
|
|
|
pNetRootContext =
|
|
|
|
|
NFS41GetNetRootExtension(cur->srv_open->pVNetRoot->pNetRoot);
|
|
|
|
|
/* place an upcall for this srv_open */
|
|
|
|
|
status = nfs41_UpcallCreate(NFS41_FILE_QUERY,
|
|
|
|
|
&cur->nfs41_fobx->sec_ctx, pVNetRootContext->session,
|
|
|
|
|
cur->nfs41_fobx->nfs41_open_state,
|
2012-02-13 16:08:21 -05:00
|
|
|
pNetRootContext->nfs41d_version,
|
|
|
|
|
cur->srv_open->pAlreadyPrefixedName, &entry);
|
2012-02-08 18:24:19 -05:00
|
|
|
if (status)
|
|
|
|
|
goto out;
|
|
|
|
|
entry->u.QueryFile.InfoClass = FileBasicInformation;
|
|
|
|
|
entry->u.QueryFile.buf = &binfo;
|
|
|
|
|
entry->u.QueryFile.buf_len = sizeof(binfo);
|
|
|
|
|
|
|
|
|
|
if (nfs41_UpcallWaitForReply(entry) != STATUS_SUCCESS) {
|
|
|
|
|
status = STATUS_INTERNAL_ERROR;
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
if (cur->ChangeTime != entry->u.QueryFile.ChangeTime) {
|
|
|
|
|
ULONG flag = DISABLE_CACHING;
|
|
|
|
|
DbgP("srvopen_main: old ctime=%llu new_ctime=%llu\n",
|
|
|
|
|
cur->ChangeTime, entry->u.QueryFile.ChangeTime);
|
2012-02-13 16:08:21 -05:00
|
|
|
DbgP("srvopen_main: ************ Invalidate the cache for %wZ "
|
|
|
|
|
"************\n", cur->srv_open->pAlreadyPrefixedName);
|
2012-02-08 18:24:19 -05:00
|
|
|
RxChangeBufferingState((PSRV_OPEN)cur->srv_open,
|
|
|
|
|
ULongToPtr(flag), 1);
|
|
|
|
|
cur->ChangeTime = entry->u.QueryFile.ChangeTime;
|
|
|
|
|
cur->skip = TRUE;
|
|
|
|
|
}
|
|
|
|
|
nfs41_fcb = (PNFS41_FCB)cur->srv_open->pFcb->Context;
|
|
|
|
|
nfs41_fcb->changeattr = entry->u.QueryFile.ChangeTime;
|
|
|
|
|
RxFreePool(entry);
|
|
|
|
|
out:
|
|
|
|
|
if (pEntry->Flink == &openlist->head) {
|
|
|
|
|
DbgP("srvopen_main: reached end of the list\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
pEntry = pEntry->Flink;
|
|
|
|
|
}
|
|
|
|
|
ExReleaseFastMutex(&srvopenLock);
|
|
|
|
|
}
|
|
|
|
|
DbgEx();
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 15:53:17 -05:00
|
|
|
NTSTATUS DriverEntry(
|
|
|
|
|
IN PDRIVER_OBJECT drv,
|
|
|
|
|
IN PUNICODE_STRING path)
|
2010-10-11 14:59:26 -04:00
|
|
|
{
|
|
|
|
|
NTSTATUS status;
|
|
|
|
|
ULONG flags = 0, i;
|
|
|
|
|
UNICODE_STRING dev_name, user_dev_name;
|
|
|
|
|
PNFS41_DEVICE_EXTENSION dev_exts;
|
2010-11-02 13:45:08 -04:00
|
|
|
TIME_FIELDS jan_1_1970 = {1970, 1, 1, 0, 0, 0, 0, 0};
|
2012-02-08 18:24:19 -05:00
|
|
|
ACCESS_MASK mask = 0;
|
|
|
|
|
OBJECT_ATTRIBUTES oattrs;
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
DbgEn();
|
|
|
|
|
|
|
|
|
|
status = RxDriverEntry(drv, path);
|
|
|
|
|
if (status != STATUS_SUCCESS) {
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("RxDriverEntry failed: %08lx\n", status);
|
2010-10-11 14:59:26 -04:00
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RtlInitUnicodeString(&dev_name, NFS41_DEVICE_NAME);
|
|
|
|
|
SetFlag(flags, RX_REGISTERMINI_FLAG_DONT_PROVIDE_MAILSLOTS);
|
|
|
|
|
|
|
|
|
|
status = nfs41_init_ops();
|
|
|
|
|
if (status != STATUS_SUCCESS) {
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("nfs41_init_ops failed to initialize dispatch table\n");
|
2010-10-11 14:59:26 -04:00
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DbgP("calling RxRegisterMinirdr\n");
|
|
|
|
|
status = RxRegisterMinirdr(&nfs41_dev, drv, &nfs41_ops, flags, &dev_name,
|
|
|
|
|
sizeof(NFS41_DEVICE_EXTENSION),
|
|
|
|
|
FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_REMOTE_DEVICE);
|
|
|
|
|
if (status != STATUS_SUCCESS) {
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("RxRegisterMinirdr failed: %08lx\n", status);
|
2010-10-11 14:59:26 -04:00
|
|
|
goto out;
|
|
|
|
|
}
|
|
|
|
|
nfs41_dev->Flags |= DO_BUFFERED_IO;
|
|
|
|
|
|
|
|
|
|
dev_exts = (PNFS41_DEVICE_EXTENSION)
|
|
|
|
|
((PBYTE)(nfs41_dev) + sizeof(RDBSS_DEVICE_OBJECT));
|
|
|
|
|
|
|
|
|
|
RxDefineNode(dev_exts, NFS41_DEVICE_EXTENSION);
|
|
|
|
|
dev_exts->DeviceObject = nfs41_dev;
|
2011-12-22 14:50:53 -05:00
|
|
|
nfs41_create_volume_info((PFILE_FS_VOLUME_INFORMATION)dev_exts->VolAttrs,
|
|
|
|
|
&dev_exts->VolAttrsLen);
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
RtlInitUnicodeString(&user_dev_name, NFS41_SHADOW_DEVICE_NAME);
|
|
|
|
|
DbgP("calling IoCreateSymbolicLink %wZ %wZ\n", &user_dev_name, &dev_name);
|
|
|
|
|
status = IoCreateSymbolicLink(&user_dev_name, &dev_name);
|
|
|
|
|
if (status != STATUS_SUCCESS) {
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("Device name IoCreateSymbolicLink failed: %08lx\n", status);
|
2010-10-11 14:59:26 -04:00
|
|
|
goto out_unregister;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
KeInitializeEvent(&upcallEvent, SynchronizationEvent, FALSE );
|
|
|
|
|
ExInitializeFastMutex(&upcallLock);
|
|
|
|
|
ExInitializeFastMutex(&downcallLock);
|
|
|
|
|
ExInitializeFastMutex(&xidLock);
|
|
|
|
|
ExInitializeFastMutex(&openOwnerLock);
|
2012-02-08 18:24:19 -05:00
|
|
|
ExInitializeFastMutex(&srvopenLock);
|
2010-10-11 14:59:26 -04:00
|
|
|
upcall = RxAllocatePoolWithTag(NonPagedPool, sizeof(nfs41_updowncall_list),
|
|
|
|
|
NFS41_MM_POOLTAG);
|
|
|
|
|
if (upcall == NULL)
|
|
|
|
|
goto out_unregister;
|
|
|
|
|
InitializeListHead(&upcall->head);
|
|
|
|
|
downcall = RxAllocatePoolWithTag(NonPagedPool, sizeof(nfs41_updowncall_list),
|
|
|
|
|
NFS41_MM_POOLTAG);
|
|
|
|
|
if (downcall == NULL) {
|
|
|
|
|
RxFreePool(upcall);
|
|
|
|
|
goto out_unregister;
|
|
|
|
|
}
|
|
|
|
|
InitializeListHead(&downcall->head);
|
2012-02-08 18:24:19 -05:00
|
|
|
openlist = RxAllocatePoolWithTag(NonPagedPool, sizeof(nfs41_srvopen_list),
|
|
|
|
|
NFS41_MM_POOLTAG);
|
|
|
|
|
if (openlist == NULL) {
|
|
|
|
|
RxFreePool(upcall);
|
|
|
|
|
RxFreePool(downcall);
|
|
|
|
|
goto out_unregister;
|
|
|
|
|
}
|
|
|
|
|
InitializeListHead(&openlist->head);
|
|
|
|
|
InitializeObjectAttributes(&oattrs, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
|
|
|
|
|
status = PsCreateSystemThread(&dev_exts->openlistHandle, mask,
|
|
|
|
|
&oattrs, NULL, NULL, &srvopen_main, NULL);
|
|
|
|
|
if (status != STATUS_SUCCESS) {
|
|
|
|
|
RxFreePool(upcall);
|
|
|
|
|
RxFreePool(downcall);
|
|
|
|
|
RxFreePool(openlist);
|
|
|
|
|
goto out;
|
|
|
|
|
}
|
2010-10-11 14:59:26 -04:00
|
|
|
|
|
|
|
|
drv->DriverUnload = nfs41_driver_unload;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
|
|
|
|
|
drv->MajorFunction[i] = (PDRIVER_DISPATCH)nfs41_FsdDispatch;
|
|
|
|
|
|
2010-10-27 14:58:35 -04:00
|
|
|
RtlTimeFieldsToTime(&jan_1_1970, &unix_time_diff);
|
|
|
|
|
|
2010-10-11 14:59:26 -04:00
|
|
|
out_unregister:
|
|
|
|
|
if (status != STATUS_SUCCESS)
|
|
|
|
|
RxUnregisterMinirdr(nfs41_dev);
|
|
|
|
|
out:
|
|
|
|
|
DbgEx();
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID nfs41_driver_unload(IN PDRIVER_OBJECT drv)
|
|
|
|
|
{
|
|
|
|
|
PRX_CONTEXT RxContext;
|
|
|
|
|
NTSTATUS status;
|
|
|
|
|
UNICODE_STRING dev_name, pipe_name;
|
|
|
|
|
|
|
|
|
|
DbgEn();
|
|
|
|
|
|
|
|
|
|
RxContext = RxCreateRxContext(NULL, nfs41_dev, RX_CONTEXT_FLAG_IN_FSP);
|
|
|
|
|
if (RxContext == NULL) {
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
|
goto unload;
|
|
|
|
|
}
|
|
|
|
|
status = RxStopMinirdr(RxContext, &RxContext->PostRequest);
|
|
|
|
|
RxDereferenceAndDeleteRxContext(RxContext);
|
|
|
|
|
|
|
|
|
|
unload:
|
|
|
|
|
RtlInitUnicodeString(&dev_name, NFS41_SHADOW_DEVICE_NAME);
|
|
|
|
|
status = IoDeleteSymbolicLink(&dev_name);
|
|
|
|
|
if (status != STATUS_SUCCESS) {
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("couldn't delete device symbolic link\n");
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
RtlInitUnicodeString(&pipe_name, NFS41_SHADOW_PIPE_NAME);
|
|
|
|
|
status = IoDeleteSymbolicLink(&pipe_name);
|
|
|
|
|
if (status != STATUS_SUCCESS) {
|
2010-11-05 13:56:11 -04:00
|
|
|
print_error("couldn't delete pipe symbolic link\n");
|
2010-10-11 14:59:26 -04:00
|
|
|
}
|
|
|
|
|
if (upcall)
|
|
|
|
|
RxFreePool(upcall);
|
|
|
|
|
if (downcall)
|
|
|
|
|
RxFreePool(downcall);
|
|
|
|
|
RxUnload(drv);
|
|
|
|
|
|
|
|
|
|
DbgP("driver unloaded %p\n", drv);
|
|
|
|
|
DbgR();
|
|
|
|
|
}
|