ReactOS 0.4.15-dev-7681-g776c3a3
nfs41_driver.c
Go to the documentation of this file.
1/* NFSv4.1 client for Windows
2 * Copyright © 2012 The Regents of the University of Michigan
3 *
4 * Olga Kornievskaia <aglo@umich.edu>
5 * Casey Bodley <cbodley@umich.edu>
6 *
7 * This library is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or (at
10 * your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful, but
13 * without any warranty; without even the implied warranty of merchantability
14 * or fitness for a particular purpose. See the GNU Lesser General Public
15 * License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 */
21
22#define MINIRDR__NAME "Value is ignored, only fact of definition"
23#include <rx.h>
24#include <windef.h>
25#include <winerror.h>
26
27#include <ntstrsafe.h>
28
29#ifdef __REACTOS__
30#include <pseh/pseh2.h>
31#endif
32
33#include "nfs41_driver.h"
34#include "nfs41_np.h"
35#include "nfs41_debug.h"
36
37#if defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7)
38NTSTATUS NTAPI RtlUnicodeToUTF8N(CHAR *utf8_dest, ULONG utf8_bytes_max,
39 ULONG *utf8_bytes_written,
40 const WCHAR *uni_src, ULONG uni_bytes);
41NTSTATUS NTAPI RtlUTF8ToUnicodeN(WCHAR *uni_dest, ULONG uni_bytes_max,
42 ULONG *uni_bytes_written,
43 const CHAR *utf8_src, ULONG utf8_bytes);
44#endif /* defined(__REACTOS__) && (NTDDI_VERSION < NTDDI_WIN7) */
45
46#define USE_MOUNT_SEC_CONTEXT
47
48/* debugging printout defines */
49//#define DEBUG_FSDDISPATCH
50#define DEBUG_MARSHAL_HEADER
51#define DEBUG_MARSHAL_DETAIL
52//#define DEBUG_OPEN
53//#define DEBUG_CLOSE
54//#define DEBUG_CACHE
55#define DEBUG_INVALIDATE_CACHE
56//#define DEBUG_READ
57//#define DEBUG_WRITE
58//#define DEBUG_DIR_QUERY
59//#define DEBUG_FILE_QUERY
60//#define DEBUG_FILE_SET
61//#define DEBUG_ACL_QUERY
62//#define DEBUG_ACL_SET
63//#define DEBUG_EA_QUERY
64//#define DEBUG_EA_SET
65//#define DEBUG_LOCK
66//#define DEBUG_MISC
67#define DEBUG_TIME_BASED_COHERENCY
68#define DEBUG_MOUNT
69//#define DEBUG_VOLUME_QUERY
70
71//#define ENABLE_TIMINGS
72//#define ENABLE_INDV_TIMINGS
73#ifdef ENABLE_TIMINGS
74typedef struct __nfs41_timings {
75 LONG tops, sops;
76 LONGLONG ticks, size;
77} nfs41_timings;
78
79nfs41_timings lookup, readdir, open, close, getattr, setattr, getacl, setacl, volume,
80 read, write, lock, unlock, setexattr, getexattr;
81#endif
82DRIVER_INITIALIZE DriverEntry;
83DRIVER_UNLOAD nfs41_driver_unload;
85
88
89#define DISABLE_CACHING 0
90#define ENABLE_READ_CACHING 1
91#define ENABLE_WRITE_CACHING 2
92#define ENABLE_READWRITE_CACHING 3
93
94#define NFS41_MM_POOLTAG ('nfs4')
95#define NFS41_MM_POOLTAG_ACL ('acls')
96#define NFS41_MM_POOLTAG_MOUNT ('mnts')
97#define NFS41_MM_POOLTAG_OPEN ('open')
98#define NFS41_MM_POOLTAG_UP ('upca')
99#define NFS41_MM_POOLTAG_DOWN ('down')
100
105
108
109#define DECLARE_CONST_ANSI_STRING(_var, _string) \
110 const CHAR _var ## _buffer[] = _string; \
111 const ANSI_STRING _var = { sizeof(_string) - sizeof(CHAR), \
112 sizeof(_string), (PCH) _var ## _buffer }
113#define RELATIVE(wait) (-(wait))
114#define NANOSECONDS(nanos) (((signed __int64)(nanos)) / 100L)
115#define MICROSECONDS(micros) (((signed __int64)(micros)) * NANOSECONDS(1000L))
116#define MILLISECONDS(milli) (((signed __int64)(milli)) * MICROSECONDS(1000L))
117#define SECONDS(seconds) (((signed __int64)(seconds)) * MILLISECONDS(1000L))
118
119DECLARE_CONST_ANSI_STRING(NfsV3Attributes, "NfsV3Attributes");
120DECLARE_CONST_ANSI_STRING(NfsSymlinkTargetName, "NfsSymlinkTargetName");
121DECLARE_CONST_ANSI_STRING(NfsActOnLink, "NfsActOnLink");
122
124 IN const ANSI_STRING *lhs,
125 IN const CHAR *rhs,
126 IN const UCHAR rhs_len)
127{
128 return lhs->Length == rhs_len &&
129 RtlCompareMemory(lhs->Buffer, rhs, rhs_len) == rhs_len;
130}
131
132typedef struct _nfs3_attrs {
135 struct {
142LARGE_INTEGER unix_time_diff; //needed to convert windows time to unix
143
144enum ftype3 {
151 NF3FIFO
153
160
161#ifdef __REACTOS__
162#undef _errno
163#undef errno
164#endif
165
166typedef struct _updowncall_entry {
185 union {
186 struct {
195 struct {
200 struct {
206 struct {
210 struct {
228 struct {
233 struct {
242 struct {
245 struct {
246 DWORD mode;
248 struct {
256 struct {
260 struct {
263 struct {
266 } u;
267
269
270typedef struct _updowncall_list {
274
275typedef struct _nfs41_mount_entry {
283
284typedef struct _nfs41_mount_list {
287
288#define nfs41_AddEntry(lock,list,pEntry) \
289 ExAcquireFastMutex(&lock); \
290 InsertTailList(&(list).head, &(pEntry)->next); \
291 ExReleaseFastMutex(&lock);
292#define nfs41_RemoveFirst(lock,list,pEntry) \
293 ExAcquireFastMutex(&lock); \
294 pEntry = (IsListEmpty(&(list).head) \
295 ? NULL \
296 : RemoveHeadList(&(list).head)); \
297 ExReleaseFastMutex(&lock);
298#define nfs41_RemoveEntry(lock,pEntry) \
299 ExAcquireFastMutex(&lock); \
300 RemoveEntryList(&pEntry->next); \
301 ExReleaseFastMutex(&lock);
302#define nfs41_IsListEmpty(lock,list,flag) \
303 ExAcquireFastMutex(&lock); \
304 flag = IsListEmpty(&(list).head); \
305 ExReleaseFastMutex(&lock);
306#define nfs41_GetFirstEntry(lock,list,pEntry) \
307 ExAcquireFastMutex(&lock); \
308 pEntry = (IsListEmpty(&(list).head) \
309 ? NULL \
310 : (nfs41_updowncall_entry *) \
311 (CONTAINING_RECORD((list).head.Flink, \
312 nfs41_updowncall_entry, \
313 next))); \
314 ExReleaseFastMutex(&lock);
315#define nfs41_GetFirstMountEntry(lock,list,pEntry) \
316 ExAcquireFastMutex(&lock); \
317 pEntry = (IsListEmpty(&(list).head) \
318 ? NULL \
319 : (nfs41_mount_entry *) \
320 (CONTAINING_RECORD((list).head.Flink, \
321 nfs41_mount_entry, \
322 next))); \
323 ExReleaseFastMutex(&lock);
324
325/* In order to cooperate with other network providers,
326 * we only claim paths of the format '\\server\nfs4\path' */
327DECLARE_CONST_UNICODE_STRING(NfsPrefix, L"\\nfs4");
328DECLARE_CONST_UNICODE_STRING(AUTH_SYS_NAME, L"sys");
329DECLARE_CONST_UNICODE_STRING(AUTHGSS_KRB5_NAME, L"krb5");
330DECLARE_CONST_UNICODE_STRING(AUTHGSS_KRB5I_NAME, L"krb5i");
331DECLARE_CONST_UNICODE_STRING(AUTHGSS_KRB5P_NAME, L"krb5p");
334
335#define SERVER_NAME_BUFFER_SIZE 1024
336#define MOUNT_CONFIG_RW_SIZE_MIN 1024
337#define MOUNT_CONFIG_RW_SIZE_DEFAULT 1048576
338#define MOUNT_CONFIG_RW_SIZE_MAX 1048576
339#define MAX_SEC_FLAVOR_LEN 12
340#define UPCALL_TIMEOUT_DEFAULT 50 /* in seconds */
341
342typedef struct _NFS41_MOUNT_CONFIG {
356
365#define NFS41GetNetRootExtension(pNetRoot) \
366 (((pNetRoot) == NULL) ? NULL : \
367 (PNFS41_NETROOT_EXTENSION)((pNetRoot)->Context))
368
369/* FileSystemName as reported by FileFsAttributeInfo query */
370#define FS_NAME L"NFS"
371#define FS_NAME_LEN (sizeof(FS_NAME) - sizeof(WCHAR))
372#define FS_ATTR_LEN (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + FS_NAME_LEN)
373
374/* FileSystemName as reported by FileFsAttributeInfo query */
375#define VOL_NAME L"PnfsVolume"
376#define VOL_NAME_LEN (sizeof(VOL_NAME) - sizeof(WCHAR))
377#define VOL_ATTR_LEN (sizeof(FILE_FS_VOLUME_INFORMATION) + VOL_NAME_LEN)
378
390#define STORE_MOUNT_SEC_CONTEXT
391#ifdef STORE_MOUNT_SEC_CONTEXT
393#endif
395#define NFS41GetVNetRootExtension(pVNetRoot) \
396 (((pVNetRoot) == NULL) ? NULL : \
397 (PNFS41_V_NET_ROOT_EXTENSION)((pVNetRoot)->Context))
398
399typedef struct _NFS41_FCB {
409#define NFS41GetFcbExtension(pFcb) \
410 (((pFcb) == NULL) ? NULL : (PNFS41_FCB)((pFcb)->Context))
411
412typedef struct _NFS41_FOBX {
415
425#define NFS41GetFobxExtension(pFobx) \
426 (((pFobx) == NULL) ? NULL : (PNFS41_FOBX)((pFobx)->Context))
427
428typedef struct _NFS41_SERVER_ENTRY {
431 UNICODE_STRING Name; // the server name.
433
445
446#define NFS41GetDeviceExtension(RxContext,pExt) \
447 PNFS41_DEVICE_EXTENSION pExt = (PNFS41_DEVICE_EXTENSION) \
448 ((PBYTE)(RxContext->RxDeviceObject) + sizeof(RDBSS_DEVICE_OBJECT))
449
450typedef struct _nfs41_fcb_list_entry {
458
459typedef struct _nfs41_fcb_list {
463
467#define RxDefineNode( node, type ) \
468 node->NodeTypeCode = NTC_##type; \
469 node->NodeByteSize = sizeof(type);
470
471#define RDR_NULL_STATE 0
472#define RDR_UNLOADED 1
473#define RDR_UNLOADING 2
474#define RDR_LOADING 3
475#define RDR_LOADED 4
476#define RDR_STOPPED 5
477#define RDR_STOPPING 6
478#define RDR_STARTING 7
479#define RDR_STARTED 8
480
483
485
487 PRX_CONTEXT RxContext)
488{
489
491
492 if (IrpSp) {
493 DbgP("FileOject %p name %wZ access r=%d,w=%d,d=%d share r=%d,w=%d,d=%d\n",
494 IrpSp->FileObject, &IrpSp->FileObject->FileName,
495 IrpSp->FileObject->ReadAccess, IrpSp->FileObject->WriteAccess,
496 IrpSp->FileObject->DeleteAccess, IrpSp->FileObject->SharedRead,
497 IrpSp->FileObject->SharedWrite, IrpSp->FileObject->SharedDelete);
499 print_irps_flags(0, RxContext->CurrentIrpSp);
500 } else
501 DbgP("Couldn't print FileObject IrpSp is NULL\n");
502
503 print_fo_all(1, RxContext);
504 if (RxContext->CurrentIrp)
505 print_irp_flags(0, RxContext->CurrentIrp);
506}
507
508/* convert strings from unicode -> ansi during marshalling to
509 * save space in the upcall buffers and avoid extra copies */
512{
513 ULONG ActualCount = 0;
514 RtlUnicodeToUTF8N(NULL, 0xffff, &ActualCount, str->Buffer, str->Length);
515 return sizeof(str->MaximumLength) + ActualCount + sizeof(UNICODE_NULL);
516}
517
519 IN OUT unsigned char **pos,
521{
522 ANSI_STRING ansi;
523 ULONG ActualCount;
525
526 if (str->Length == 0) {
528 ActualCount = 0;
529 ansi.MaximumLength = 1;
530 goto out_copy;
531 }
532
533 /* query the number of bytes required for the utf8 encoding */
534 status = RtlUnicodeToUTF8N(NULL, 0xffff,
535 &ActualCount, str->Buffer, str->Length);
536 if (status) {
537 print_error("RtlUnicodeToUTF8N('%wZ') failed with 0x%08X\n",
538 str, status);
539 goto out;
540 }
541
542 /* convert the string directly into the upcall buffer */
543 ansi.Buffer = (PCHAR)*pos + sizeof(ansi.MaximumLength);
544 ansi.MaximumLength = (USHORT)ActualCount + sizeof(UNICODE_NULL);
546 &ActualCount, str->Buffer, str->Length);
547 if (status) {
548 print_error("RtlUnicodeToUTF8N(%hu, '%wZ', %hu) failed with 0x%08X\n",
549 ansi.MaximumLength, str, str->Length, status);
550 goto out;
551 }
552
553out_copy:
554 RtlCopyMemory(*pos, &ansi.MaximumLength, sizeof(ansi.MaximumLength));
555 *pos += sizeof(ansi.MaximumLength);
556 (*pos)[ActualCount] = '\0';
557 *pos += ansi.MaximumLength;
558out:
559 return status;
560}
561
564 unsigned char *buf,
565 ULONG buf_len,
566 ULONG *len)
567{
569 ULONG header_len = 0;
570 unsigned char *tmp = buf;
571
572 header_len = sizeof(entry->version) + sizeof(entry->xid) +
573 sizeof(entry->opcode) + 2 * sizeof(HANDLE);
574 if (header_len > buf_len) {
576 goto out;
577 }
578 else
579 *len = header_len;
580 RtlCopyMemory(tmp, &entry->version, sizeof(entry->version));
581 tmp += sizeof(entry->version);
582 RtlCopyMemory(tmp, &entry->xid, sizeof(entry->xid));
583 tmp += sizeof(entry->xid);
584 RtlCopyMemory(tmp, &entry->opcode, sizeof(entry->opcode));
585 tmp += sizeof(entry->opcode);
586 RtlCopyMemory(tmp, &entry->session, sizeof(HANDLE));
587 tmp += sizeof(HANDLE);
588 RtlCopyMemory(tmp, &entry->open_state, sizeof(HANDLE));
589 tmp += sizeof(HANDLE);
590
591#ifdef DEBUG_MARSHAL_HEADER
592 if (MmIsAddressValid(entry->filename))
593 DbgP("[upcall header] xid=%lld opcode=%s filename=%wZ version=%d "
594 "session=0x%x open_state=0x%x\n", entry->xid,
595 opcode2string(entry->opcode), entry->filename,
596 entry->version, entry->session, entry->open_state);
597 else
599#endif
600out:
601 return status;
602}
603
606{
607 switch(sec_flavor) {
608 case RPCSEC_AUTH_SYS: return "AUTH_SYS";
609 case RPCSEC_AUTHGSS_KRB5: return "AUTHGSS_KRB5";
610 case RPCSEC_AUTHGSS_KRB5I: return "AUTHGSS_KRB5I";
611 case RPCSEC_AUTHGSS_KRB5P: return "AUTHGSS_KRB5P";
612 }
613
614 return "UNKNOWN FLAVOR";
615}
618 unsigned char *buf,
619 ULONG buf_len,
620 ULONG *len)
621{
623 ULONG header_len = 0;
624 unsigned char *tmp = buf;
625
626 status = marshal_nfs41_header(entry, tmp, buf_len, len);
627 if (status) goto out;
628 else tmp += *len;
629
630 /* 03/25/2011: Kernel crash to nfsd not running but mount upcall cued up */
631 if (!MmIsAddressValid(entry->u.Mount.srv_name) ||
632 !MmIsAddressValid(entry->u.Mount.root)) {
634 goto out;
635 }
636 header_len = *len + length_as_utf8(entry->u.Mount.srv_name) +
637 length_as_utf8(entry->u.Mount.root) + 3 * sizeof(DWORD);
638 if (header_len > buf_len) {
640 goto out;
641 }
642 status = marshall_unicode_as_utf8(&tmp, entry->u.Mount.srv_name);
643 if (status) goto out;
644 status = marshall_unicode_as_utf8(&tmp, entry->u.Mount.root);
645 if (status) goto out;
646 RtlCopyMemory(tmp, &entry->u.Mount.sec_flavor, sizeof(DWORD));
647 tmp += sizeof(DWORD);
648 RtlCopyMemory(tmp, &entry->u.Mount.rsize, sizeof(DWORD));
649 tmp += sizeof(DWORD);
650 RtlCopyMemory(tmp, &entry->u.Mount.wsize, sizeof(DWORD));
651
652 *len = header_len;
653
654#ifdef DEBUG_MARSHAL_DETAIL
655 DbgP("marshal_nfs41_mount: server name=%wZ mount point=%wZ sec_flavor=%s "
656 "rsize=%d wsize=%d\n", entry->u.Mount.srv_name, entry->u.Mount.root,
657 secflavorop2name(entry->u.Mount.sec_flavor), entry->u.Mount.rsize,
658 entry->u.Mount.wsize);
659#endif
660out:
661 return status;
662}
663
666 unsigned char *buf,
667 ULONG buf_len,
668 ULONG *len)
669{
670 return marshal_nfs41_header(entry, buf, buf_len, len);
671}
672
675 unsigned char *buf,
676 ULONG buf_len,
677 ULONG *len)
678{
680 ULONG header_len = 0;
681 unsigned char *tmp = buf;
682
683 status = marshal_nfs41_header(entry, tmp, buf_len, len);
684 if (status) goto out;
685 else tmp += *len;
686
687 header_len = *len + length_as_utf8(entry->filename) +
688 7 * sizeof(ULONG) + 2 * sizeof(HANDLE) +
689 length_as_utf8(&entry->u.Open.symlink);
690 if (header_len > buf_len) {
692 goto out;
693 }
694 status = marshall_unicode_as_utf8(&tmp, entry->filename);
695 if (status) goto out;
696 RtlCopyMemory(tmp, &entry->u.Open.access_mask,
697 sizeof(entry->u.Open.access_mask));
698 tmp += sizeof(entry->u.Open.access_mask);
699 RtlCopyMemory(tmp, &entry->u.Open.access_mode,
700 sizeof(entry->u.Open.access_mode));
701 tmp += sizeof(entry->u.Open.access_mode);
702 RtlCopyMemory(tmp, &entry->u.Open.attrs, sizeof(entry->u.Open.attrs));
703 tmp += sizeof(entry->u.Open.attrs);
704 RtlCopyMemory(tmp, &entry->u.Open.copts, sizeof(entry->u.Open.copts));
705 tmp += sizeof(entry->u.Open.copts);
706 RtlCopyMemory(tmp, &entry->u.Open.disp, sizeof(entry->u.Open.disp));
707 tmp += sizeof(entry->u.Open.disp);
708 RtlCopyMemory(tmp, &entry->u.Open.open_owner_id,
709 sizeof(entry->u.Open.open_owner_id));
710 tmp += sizeof(entry->u.Open.open_owner_id);
711 RtlCopyMemory(tmp, &entry->u.Open.mode, sizeof(DWORD));
712 tmp += sizeof(DWORD);
713 RtlCopyMemory(tmp, &entry->u.Open.srv_open, sizeof(HANDLE));
714 tmp += sizeof(HANDLE);
715 status = marshall_unicode_as_utf8(&tmp, &entry->u.Open.symlink);
716 if (status) goto out;
717
718 _SEH2_TRY {
719 if (entry->u.Open.EaMdl) {
720 entry->u.Open.EaBuffer =
722#ifndef __REACTOS__
724#else
726#endif
727 if (entry->u.Open.EaBuffer == NULL) {
728 print_error("MmMapLockedPagesSpecifyCache failed to map pages\n");
730 goto out;
731 }
732 }
734 print_error("Call to MmMapLocked failed due to exception 0x%x\n", _SEH2_GetExceptionCode());
736 goto out;
737 } _SEH2_END;
738 RtlCopyMemory(tmp, &entry->u.Open.EaBuffer, sizeof(HANDLE));
739 *len = header_len;
740
741#ifdef DEBUG_MARSHAL_DETAIL
742 DbgP("marshal_nfs41_open: name=%wZ mask=0x%x access=0x%x attrs=0x%x "
743 "opts=0x%x dispo=0x%x open_owner_id=0x%x mode=%o srv_open=%p ea=%p\n",
744 entry->filename, entry->u.Open.access_mask,
745 entry->u.Open.access_mode, entry->u.Open.attrs, entry->u.Open.copts,
746 entry->u.Open.disp, entry->u.Open.open_owner_id, entry->u.Open.mode,
747 entry->u.Open.srv_open, entry->u.Open.EaBuffer);
748#endif
749out:
750 return status;
751}
752
755 unsigned char *buf,
756 ULONG buf_len,
757 ULONG *len)
758{
760 ULONG header_len = 0;
761 unsigned char *tmp = buf;
762
763 status = marshal_nfs41_header(entry, tmp, buf_len, len);
764 if (status) goto out;
765 else tmp += *len;
766
767 header_len = *len + sizeof(entry->buf_len) +
768 sizeof(entry->u.ReadWrite.offset) + sizeof(HANDLE);
769 if (header_len > buf_len) {
771 goto out;
772 }
773
774 RtlCopyMemory(tmp, &entry->buf_len, sizeof(entry->buf_len));
775 tmp += sizeof(entry->buf_len);
776 RtlCopyMemory(tmp, &entry->u.ReadWrite.offset,
777 sizeof(entry->u.ReadWrite.offset));
778 tmp += sizeof(entry->u.ReadWrite.offset);
779 _SEH2_TRY {
780 entry->u.ReadWrite.MdlAddress->MdlFlags |= MDL_MAPPING_CAN_FAIL;
781 entry->buf =
782 MmMapLockedPagesSpecifyCache(entry->u.ReadWrite.MdlAddress,
783#ifndef __REACTOS__
785#else
787#endif
788 if (entry->buf == NULL) {
789 print_error("MmMapLockedPagesSpecifyCache failed to map pages\n");
791 goto out;
792 }
796 print_error("Call to MmMapLocked failed due to exception 0x%x\n", code);
798 goto out;
799 } _SEH2_END;
800 RtlCopyMemory(tmp, &entry->buf, sizeof(HANDLE));
801 *len = header_len;
802
803#ifdef DEBUG_MARSHAL_DETAIL
804 DbgP("marshal_nfs41_rw: len=%lu offset=%llu MdlAddress=%p Userspace=%p\n",
805 entry->buf_len, entry->u.ReadWrite.offset,
806 entry->u.ReadWrite.MdlAddress, entry->buf);
807#endif
808out:
809 return status;
810}
811
814 unsigned char *buf,
815 ULONG buf_len,
816 ULONG *len)
817{
819 ULONG header_len = 0;
820 unsigned char *tmp = buf;
821
822 status = marshal_nfs41_header(entry, tmp, buf_len, len);
823 if (status) goto out;
824 else tmp += *len;
825
826 header_len = *len + 2 * sizeof(LONGLONG) + 2 * sizeof(BOOLEAN);
827 if (header_len > buf_len) {
829 goto out;
830 }
831 RtlCopyMemory(tmp, &entry->u.Lock.offset, sizeof(LONGLONG));
832 tmp += sizeof(LONGLONG);
833 RtlCopyMemory(tmp, &entry->u.Lock.length, sizeof(LONGLONG));
834 tmp += sizeof(LONGLONG);
835 RtlCopyMemory(tmp, &entry->u.Lock.exclusive, sizeof(BOOLEAN));
836 tmp += sizeof(BOOLEAN);
837 RtlCopyMemory(tmp, &entry->u.Lock.blocking, sizeof(BOOLEAN));
838 *len = header_len;
839
840#ifdef DEBUG_MARSHAL_DETAIL
841 DbgP("marshal_nfs41_lock: offset=%llx length=%llx exclusive=%u "
842 "blocking=%u\n", entry->u.Lock.offset, entry->u.Lock.length,
843 entry->u.Lock.exclusive, entry->u.Lock.blocking);
844#endif
845out:
846 return status;
847}
848
851 unsigned char *buf,
852 ULONG buf_len,
853 ULONG *len)
854{
856 ULONG header_len = 0;
857 unsigned char *tmp = buf;
859
860 status = marshal_nfs41_header(entry, tmp, buf_len, len);
861 if (status) goto out;
862 else tmp += *len;
863
864 header_len = *len + sizeof(ULONG) +
865 entry->u.Unlock.count * 2 * sizeof(LONGLONG);
866 if (header_len > buf_len) {
868 goto out;
869 }
870 RtlCopyMemory(tmp, &entry->u.Unlock.count, sizeof(ULONG));
871 tmp += sizeof(ULONG);
872
873 lock = &entry->u.Unlock.locks;
874 while (lock) {
875 RtlCopyMemory(tmp, &lock->ByteOffset, sizeof(LONGLONG));
876 tmp += sizeof(LONGLONG);
877 RtlCopyMemory(tmp, &lock->Length, sizeof(LONGLONG));
878 tmp += sizeof(LONGLONG);
879 lock = lock->Next;
880 }
881 *len = header_len;
882
883#ifdef DEBUG_MARSHAL_DETAIL
884 DbgP("marshal_nfs41_unlock: count=%u\n", entry->u.Unlock.count);
885#endif
886out:
887 return status;
888}
889
892 unsigned char *buf,
893 ULONG buf_len,
894 ULONG *len)
895{
897 ULONG header_len = 0;
898 unsigned char *tmp = buf;
899
900 status = marshal_nfs41_header(entry, tmp, buf_len, len);
901 if (status) goto out;
902 else tmp += *len;
903
904 header_len = *len + sizeof(BOOLEAN) + sizeof(HANDLE);
905 if (entry->u.Close.remove)
906 header_len += length_as_utf8(entry->filename) +
907 sizeof(BOOLEAN);
908
909 if (header_len > buf_len) {
911 goto out;
912 }
913 RtlCopyMemory(tmp, &entry->u.Close.remove, sizeof(BOOLEAN));
914 tmp += sizeof(BOOLEAN);
915 RtlCopyMemory(tmp, &entry->u.Close.srv_open, sizeof(HANDLE));
916 if (entry->u.Close.remove) {
917 tmp += sizeof(HANDLE);
918 status = marshall_unicode_as_utf8(&tmp, entry->filename);
919 if (status) goto out;
920 RtlCopyMemory(tmp, &entry->u.Close.renamed, sizeof(BOOLEAN));
921 }
922 *len = header_len;
923
924#ifdef DEBUG_MARSHAL_DETAIL
925 DbgP("marshal_nfs41_close: name=%wZ remove=%d srv_open=%p renamed=%d\n",
926 entry->filename->Length?entry->filename:&SLASH,
927 entry->u.Close.remove, entry->u.Close.srv_open, entry->u.Close.renamed);
928#endif
929out:
930 return status;
931}
932
935 unsigned char *buf,
936 ULONG buf_len,
937 ULONG *len)
938{
940 ULONG header_len = 0;
941 unsigned char *tmp = buf;
942
943 status = marshal_nfs41_header(entry, tmp, buf_len, len);
944 if (status) goto out;
945 else tmp += *len;
946
947 header_len = *len + 2 * sizeof(ULONG) + sizeof(HANDLE) +
948 length_as_utf8(entry->u.QueryFile.filter) + 3 * sizeof(BOOLEAN);
949 if (header_len > buf_len) {
951 goto out;
952 }
953
954 RtlCopyMemory(tmp, &entry->u.QueryFile.InfoClass, sizeof(ULONG));
955 tmp += sizeof(ULONG);
956 RtlCopyMemory(tmp, &entry->buf_len, sizeof(ULONG));
957 tmp += sizeof(ULONG);
958 status = marshall_unicode_as_utf8(&tmp, entry->u.QueryFile.filter);
959 if (status) goto out;
960 RtlCopyMemory(tmp, &entry->u.QueryFile.initial_query, sizeof(BOOLEAN));
961 tmp += sizeof(BOOLEAN);
962 RtlCopyMemory(tmp, &entry->u.QueryFile.restart_scan, sizeof(BOOLEAN));
963 tmp += sizeof(BOOLEAN);
964 RtlCopyMemory(tmp, &entry->u.QueryFile.return_single, sizeof(BOOLEAN));
965 tmp += sizeof(BOOLEAN);
966 _SEH2_TRY {
967 entry->u.QueryFile.mdl_buf =
968 MmMapLockedPagesSpecifyCache(entry->u.QueryFile.mdl,
969#ifndef __REACTOS__
971#else
973#endif
974 if (entry->u.QueryFile.mdl_buf == NULL) {
975 print_error("MmMapLockedPagesSpecifyCache failed to map pages\n");
977 goto out;
978 }
982 print_error("Call to MmMapLocked failed due to exception 0x%x\n", code);
984 goto out;
985 } _SEH2_END;
986 RtlCopyMemory(tmp, &entry->u.QueryFile.mdl_buf, sizeof(HANDLE));
987 *len = header_len;
988
989#ifdef DEBUG_MARSHAL_DETAIL
990 DbgP("marshal_nfs41_dirquery: filter='%wZ'class=%d len=%d "
991 "1st\\restart\\single=%d\\%d\\%d\n", entry->u.QueryFile.filter,
992 entry->u.QueryFile.InfoClass, entry->buf_len,
993 entry->u.QueryFile.initial_query, entry->u.QueryFile.restart_scan,
994 entry->u.QueryFile.return_single);
995#endif
996out:
997 return status;
998}
999
1002 unsigned char *buf,
1003 ULONG buf_len,
1004 ULONG *len)
1005{
1007 ULONG header_len = 0;
1008 unsigned char *tmp = buf;
1009
1010 status = marshal_nfs41_header(entry, tmp, buf_len, len);
1011 if (status) goto out;
1012 else tmp += *len;
1013
1014 header_len = *len + 2 * sizeof(ULONG);
1015 if (header_len > buf_len) {
1017 goto out;
1018 }
1019 RtlCopyMemory(tmp, &entry->u.QueryFile.InfoClass, sizeof(ULONG));
1020 tmp += sizeof(ULONG);
1021 RtlCopyMemory(tmp, &entry->buf_len, sizeof(ULONG));
1022 tmp += sizeof(ULONG);
1023 RtlCopyMemory(tmp, &entry->session, sizeof(HANDLE));
1024 tmp += sizeof(HANDLE);
1025 RtlCopyMemory(tmp, &entry->open_state, sizeof(HANDLE));
1026 *len = header_len;
1027
1028#ifdef DEBUG_MARSHAL_DETAIL
1029 DbgP("marshal_nfs41_filequery: class=%d\n", entry->u.QueryFile.InfoClass);
1030#endif
1031out:
1032 return status;
1033}
1034
1037 unsigned char *buf,
1038 ULONG buf_len,
1039 ULONG *len)
1040{
1042 ULONG header_len = 0;
1043 unsigned char *tmp = buf;
1044
1045 status = marshal_nfs41_header(entry, tmp, buf_len, len);
1046 if (status) goto out;
1047 else tmp += *len;
1048
1049 header_len = *len + length_as_utf8(entry->filename) +
1050 2 * sizeof(ULONG) + entry->buf_len;
1051 if (header_len > buf_len) {
1053 goto out;
1054 }
1055 status = marshall_unicode_as_utf8(&tmp, entry->filename);
1056 if (status) goto out;
1057 RtlCopyMemory(tmp, &entry->u.SetFile.InfoClass, sizeof(ULONG));
1058 tmp += sizeof(ULONG);
1059 RtlCopyMemory(tmp, &entry->buf_len, sizeof(ULONG));
1060 tmp += sizeof(ULONG);
1061 RtlCopyMemory(tmp, entry->buf, entry->buf_len);
1062 *len = header_len;
1063
1064#ifdef DEBUG_MARSHAL_DETAIL
1065 DbgP("marshal_nfs41_fileset: filename='%wZ' class=%d\n",
1066 entry->filename, entry->u.SetFile.InfoClass);
1067#endif
1068out:
1069 return status;
1070}
1071
1074 unsigned char *buf,
1075 ULONG buf_len,
1076 ULONG *len)
1077{
1079 ULONG header_len = 0;
1080 unsigned char *tmp = buf;
1081
1082 status = marshal_nfs41_header(entry, tmp, buf_len, len);
1083 if (status) goto out;
1084 else tmp += *len;
1085
1086 header_len = *len + length_as_utf8(entry->filename) +
1087 sizeof(ULONG) + entry->buf_len + sizeof(DWORD);
1088 if (header_len > buf_len) {
1090 goto out;
1091 }
1092
1093 status = marshall_unicode_as_utf8(&tmp, entry->filename);
1094 if (status) goto out;
1095 RtlCopyMemory(tmp, &entry->u.SetEa.mode, sizeof(DWORD));
1096 tmp += sizeof(DWORD);
1097 RtlCopyMemory(tmp, &entry->buf_len, sizeof(ULONG));
1098 tmp += sizeof(ULONG);
1099 RtlCopyMemory(tmp, entry->buf, entry->buf_len);
1100 *len = header_len;
1101
1102#ifdef DEBUG_MARSHAL_DETAIL
1103 DbgP("marshal_nfs41_easet: filename=%wZ, buflen=%d mode=0x%x\n",
1104 entry->filename, entry->buf_len, entry->u.SetEa.mode);
1105#endif
1106out:
1107 return status;
1108}
1109
1112 unsigned char *buf,
1113 ULONG buf_len,
1114 ULONG *len)
1115{
1117 ULONG header_len = 0;
1118 unsigned char *tmp = buf;
1119
1120 status = marshal_nfs41_header(entry, tmp, buf_len, len);
1121 if (status) goto out;
1122 else tmp += *len;
1123
1124 header_len = *len + length_as_utf8(entry->filename) +
1125 3 * sizeof(ULONG) + entry->u.QueryEa.EaListLength + 2 * sizeof(BOOLEAN);
1126
1127 if (header_len > buf_len) {
1129 goto out;
1130 }
1131
1132 status = marshall_unicode_as_utf8(&tmp, entry->filename);
1133 if (status) goto out;
1134 RtlCopyMemory(tmp, &entry->u.QueryEa.EaIndex, sizeof(ULONG));
1135 tmp += sizeof(ULONG);
1136 RtlCopyMemory(tmp, &entry->u.QueryEa.RestartScan, sizeof(BOOLEAN));
1137 tmp += sizeof(BOOLEAN);
1138 RtlCopyMemory(tmp, &entry->u.QueryEa.ReturnSingleEntry, sizeof(BOOLEAN));
1139 tmp += sizeof(BOOLEAN);
1140 RtlCopyMemory(tmp, &entry->buf_len, sizeof(ULONG));
1141 tmp += sizeof(ULONG);
1142 RtlCopyMemory(tmp, &entry->u.QueryEa.EaListLength, sizeof(ULONG));
1143 tmp += sizeof(ULONG);
1144 if (entry->u.QueryEa.EaList && entry->u.QueryEa.EaListLength)
1145 RtlCopyMemory(tmp, entry->u.QueryEa.EaList,
1146 entry->u.QueryEa.EaListLength);
1147 *len = header_len;
1148
1149#ifdef DEBUG_MARSHAL_DETAIL
1150 DbgP("marshal_nfs41_eaget: filename=%wZ, index=%d list_len=%d "
1151 "rescan=%d single=%d\n", entry->filename,
1152 entry->u.QueryEa.EaIndex, entry->u.QueryEa.EaListLength,
1153 entry->u.QueryEa.RestartScan, entry->u.QueryEa.ReturnSingleEntry);
1154#endif
1155out:
1156 return status;
1157}
1158
1161 unsigned char *buf,
1162 ULONG buf_len,
1163 ULONG *len)
1164{
1166 ULONG header_len = 0;
1167 unsigned char *tmp = buf;
1168
1169 status = marshal_nfs41_header(entry, tmp, buf_len, len);
1170 if (status) goto out;
1171 else tmp += *len;
1172
1173 header_len = *len + sizeof(BOOLEAN) + length_as_utf8(entry->filename);
1174 if (entry->u.Symlink.set)
1175 header_len += length_as_utf8(entry->u.Symlink.target);
1176 if (header_len > buf_len) {
1178 goto out;
1179 }
1180
1181 status = marshall_unicode_as_utf8(&tmp, entry->filename);
1182 if (status) goto out;
1183 RtlCopyMemory(tmp, &entry->u.Symlink.set, sizeof(BOOLEAN));
1184 tmp += sizeof(BOOLEAN);
1185 if (entry->u.Symlink.set) {
1186 status = marshall_unicode_as_utf8(&tmp, entry->u.Symlink.target);
1187 if (status) goto out;
1188 }
1189 *len = header_len;
1190
1191#ifdef DEBUG_MARSHAL_DETAIL
1192 DbgP("marshal_nfs41_symlink: name %wZ symlink target %wZ\n",
1193 entry->filename,
1194 entry->u.Symlink.set?entry->u.Symlink.target : NULL);
1195#endif
1196out:
1197 return status;
1198}
1199
1202 unsigned char *buf,
1203 ULONG buf_len,
1204 ULONG *len)
1205{
1207 ULONG header_len = 0;
1208 unsigned char *tmp = buf;
1209
1210 status = marshal_nfs41_header(entry, tmp, buf_len, len);
1211 if (status) goto out;
1212 else tmp += *len;
1213
1214 header_len = *len + sizeof(FS_INFORMATION_CLASS);
1215 if (header_len > buf_len) {
1217 goto out;
1218 }
1219
1220 RtlCopyMemory(tmp, &entry->u.Volume.query, sizeof(FS_INFORMATION_CLASS));
1221 *len = header_len;
1222
1223#ifdef DEBUG_MARSHAL_DETAIL
1224 DbgP("marshal_nfs41_volume: class=%d\n", entry->u.Volume.query);
1225#endif
1226out:
1227 return status;
1228}
1229
1232 unsigned char *buf,
1233 ULONG buf_len,
1234 ULONG *len)
1235{
1237 ULONG header_len = 0;
1238 unsigned char *tmp = buf;
1239
1240 status = marshal_nfs41_header(entry, tmp, buf_len, len);
1241 if (status) goto out;
1242 else tmp += *len;
1243
1244 header_len = *len + sizeof(SECURITY_INFORMATION);
1245 if (header_len > buf_len) {
1247 goto out;
1248 }
1249
1250 RtlCopyMemory(tmp, &entry->u.Acl.query, sizeof(SECURITY_INFORMATION));
1251 *len = header_len;
1252
1253#ifdef DEBUG_MARSHAL_DETAIL
1254 DbgP("marshal_nfs41_getacl: class=0x%x\n", entry->u.Acl.query);
1255#endif
1256out:
1257 return status;
1258}
1259
1262 unsigned char *buf,
1263 ULONG buf_len,
1264 ULONG *len)
1265{
1267 ULONG header_len = 0;
1268 unsigned char *tmp = buf;
1269
1270 status = marshal_nfs41_header(entry, tmp, buf_len, len);
1271 if (status) goto out;
1272 else tmp += *len;
1273
1274 header_len = *len + sizeof(SECURITY_INFORMATION) +
1275 sizeof(ULONG) + entry->buf_len;
1276 if (header_len > buf_len) {
1278 goto out;
1279 }
1280
1281 RtlCopyMemory(tmp, &entry->u.Acl.query, sizeof(SECURITY_INFORMATION));
1282 tmp += sizeof(SECURITY_INFORMATION);
1283 RtlCopyMemory(tmp, &entry->buf_len, sizeof(ULONG));
1284 tmp += sizeof(ULONG);
1285 RtlCopyMemory(tmp, entry->buf, entry->buf_len);
1286 *len = header_len;
1287
1288#ifdef DEBUG_MARSHAL_DETAIL
1289 DbgP("marshal_nfs41_setacl: class=0x%x sec_desc_len=%lu\n",
1290 entry->u.Acl.query, entry->buf_len);
1291#endif
1292out:
1293 return status;
1294}
1295
1298 unsigned char *buf,
1299 ULONG buf_len,
1300 ULONG *len)
1301{
1302 return marshal_nfs41_header(entry, buf, buf_len, len);
1303}
1304
1306 IN PRX_CONTEXT RxContext)
1307{
1308 PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
1309 unsigned char *buf = LowIoContext->ParamsFor.IoCtl.pInputBuffer;
1311 PMRX_SRV_OPEN srv_open;
1312
1313 RtlCopyMemory(&srv_open, buf, sizeof(HANDLE));
1314#ifdef DEBUG_INVALIDATE_CACHE
1315 DbgP("nfs41_invalidate_cache: received srv_open=%p %wZ\n",
1316 srv_open, srv_open->pAlreadyPrefixedName);
1317#endif
1318 if (MmIsAddressValid(srv_open))
1320 srv_open->pFcb->pNetRoot->pSrvCall, srv_open,
1321 srv_open->Key, ULongToPtr(flag));
1322}
1323
1325 IN PRX_CONTEXT RxContext,
1327 OUT ULONG *len)
1328{
1330 PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
1331 ULONG cbOut = LowIoContext->ParamsFor.IoCtl.OutputBufferLength;
1332 unsigned char *pbOut = LowIoContext->ParamsFor.IoCtl.pOutputBuffer;
1333
1334 status = SeImpersonateClientEx(entry->psec_ctx, NULL);
1335 if (status != STATUS_SUCCESS) {
1336 print_error("SeImpersonateClientEx failed %x\n", status);
1337 goto out;
1338 }
1339
1340 switch(entry->opcode) {
1341 case NFS41_SHUTDOWN:
1342 status = marshal_nfs41_shutdown(entry, pbOut, cbOut, len);
1343 KeSetEvent(&entry->cond, 0, FALSE);
1344 break;
1345 case NFS41_MOUNT:
1346 status = marshal_nfs41_mount(entry, pbOut, cbOut, len);
1347 break;
1348 case NFS41_UNMOUNT:
1349 status = marshal_nfs41_unmount(entry, pbOut, cbOut, len);
1350 break;
1351 case NFS41_OPEN:
1352 status = marshal_nfs41_open(entry, pbOut, cbOut, len);
1353 break;
1354 case NFS41_READ:
1355 status = marshal_nfs41_rw(entry, pbOut, cbOut, len);
1356 break;
1357 case NFS41_WRITE:
1358 status = marshal_nfs41_rw(entry, pbOut, cbOut, len);
1359 break;
1360 case NFS41_LOCK:
1361 status = marshal_nfs41_lock(entry, pbOut, cbOut, len);
1362 break;
1363 case NFS41_UNLOCK:
1364 status = marshal_nfs41_unlock(entry, pbOut, cbOut, len);
1365 break;
1366 case NFS41_CLOSE:
1367 status = marshal_nfs41_close(entry, pbOut, cbOut, len);
1368 break;
1369 case NFS41_DIR_QUERY:
1370 status = marshal_nfs41_dirquery(entry, pbOut, cbOut, len);
1371 break;
1372 case NFS41_FILE_QUERY:
1373 status = marshal_nfs41_filequery(entry, pbOut, cbOut, len);
1374 break;
1375 case NFS41_FILE_SET:
1376 status = marshal_nfs41_fileset(entry, pbOut, cbOut, len);
1377 break;
1378 case NFS41_EA_SET:
1379 status = marshal_nfs41_easet(entry, pbOut, cbOut, len);
1380 break;
1381 case NFS41_EA_GET:
1382 status = marshal_nfs41_eaget(entry, pbOut, cbOut, len);
1383 break;
1384 case NFS41_SYMLINK:
1385 status = marshal_nfs41_symlink(entry, pbOut, cbOut, len);
1386 break;
1387 case NFS41_VOLUME_QUERY:
1388 status = marshal_nfs41_volume(entry, pbOut, cbOut, len);
1389 break;
1390 case NFS41_ACL_QUERY:
1391 status = marshal_nfs41_getacl(entry, pbOut, cbOut, len);
1392 break;
1393 case NFS41_ACL_SET:
1394 status = marshal_nfs41_setacl(entry, pbOut, cbOut, len);
1395 break;
1396 default:
1398 print_error("Unknown nfs41 ops %d\n", entry->opcode);
1399 }
1400
1401 if (status == STATUS_SUCCESS)
1402 print_hexbuf(0, (unsigned char *)"upcall buffer", pbOut, *len);
1403
1404out:
1405 return status;
1406}
1407
1409 IN DWORD opcode,
1410 IN PSECURITY_CLIENT_CONTEXT clnt_sec_ctx,
1412 IN HANDLE open_state,
1415 OUT nfs41_updowncall_entry **entry_out)
1416{
1421
1424 if (entry == NULL) {
1426 goto out;
1427 }
1428
1431 entry->opcode = opcode;
1433 entry->session = session;
1434 entry->open_state = open_state;
1435 entry->version = version;
1436 if (filename && filename->Length) entry->filename = filename;
1437 else if (filename && !filename->Length) entry->filename = (PUNICODE_STRING)&SLASH;
1438 else entry->filename = (PUNICODE_STRING)&EMPTY_STRING;
1439 /*XXX KeInitializeEvent will bugcheck under verifier if allocated
1440 * from PagedPool? */
1443
1444 if (clnt_sec_ctx == NULL) {
1445 SeCaptureSubjectContext(&sec_ctx);
1448 sec_qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
1449 sec_qos.EffectiveOnly = 0;
1451 1, &entry->sec_ctx);
1452 if (status != STATUS_SUCCESS) {
1453 print_error("nfs41_UpcallCreate: "
1454 "SeCreateClientSecurityFromSubjectContext failed with %x\n",
1455 status);
1457 } else
1458 entry->psec_ctx = &entry->sec_ctx;
1459 SeReleaseSubjectContext(&sec_ctx);
1460 } else
1461 entry->psec_ctx = clnt_sec_ctx;
1462
1463 *entry_out = entry;
1464out:
1465 return status;
1466}
1467
1470 IN DWORD secs)
1471{
1473
1476 if (!entry->async_op) {
1478 timeout.QuadPart = RELATIVE(SECONDS(secs));
1479 /* 02/03/2011 AGLO: it is not clear what the "right" waiting design
1480 * should be. Having non-interruptable waiting seems to be the right
1481 * approach. However, when things go wrong, the only wait to proceed
1482 * is a reboot (since "waits" are not interruptable we can't stop a
1483 * hung task. Having interruptable wait causes issues with security
1484 * context. For now, I'm making CLOSE non-interruptable but keeping
1485 * the rest interruptable so that we don't have to reboot all the time
1486 */
1487 /* 02/15/2011 cbodley: added NFS41_UNLOCK for the same reason. locking
1488 * tests were triggering an interrupted unlock, which led to a bugcheck
1489 * in CloseSrvOpen() */
1490#define MAKE_WAITONCLOSE_NONITERRUPTABLE
1491#ifdef MAKE_WAITONCLOSE_NONITERRUPTABLE
1492 if (entry->opcode == NFS41_CLOSE || entry->opcode == NFS41_UNLOCK)
1495 else {
1497 UserMode, TRUE, &timeout);
1498 }
1499 if (status != STATUS_SUCCESS) {
1500 print_wait_status(1, "[downcall]", status,
1501 opcode2string(entry->opcode), entry, entry->xid);
1502 if (status == STATUS_TIMEOUT)
1504 }
1505#else
1506
1508#endif
1509 print_wait_status(0, "[downcall]", status, opcode2string(entry->opcode),
1510 entry, entry->xid);
1511 } else
1512 goto out;
1513
1514 switch(status) {
1515 case STATUS_SUCCESS: break;
1516 case STATUS_USER_APC:
1517 case STATUS_ALERTED:
1518 default:
1519 ExAcquireFastMutex(&entry->lock);
1520 if (entry->state == NFS41_DONE_PROCESSING) {
1521 ExReleaseFastMutex(&entry->lock);
1522 break;
1523 }
1524 DbgP("[upcall] abandoning %s entry=%p xid=%lld\n",
1525 opcode2string(entry->opcode), entry, entry->xid);
1526 entry->state = NFS41_NOT_WAITING;
1527 ExReleaseFastMutex(&entry->lock);
1528 goto out;
1529 }
1531out:
1532 return status;
1533}
1534
1536 IN PRX_CONTEXT RxContext)
1537{
1540 ULONG len = 0;
1542
1543process_upcall:
1545 if (pEntry) {
1548 ExAcquireFastMutex(&entry->lock);
1550 status = handle_upcall(RxContext, entry, &len);
1551 if (status == STATUS_SUCCESS &&
1554 ExReleaseFastMutex(&entry->lock);
1555 if (status) {
1556 entry->status = status;
1557 KeSetEvent(&entry->cond, 0, FALSE);
1558 RxContext->InformationToReturn = 0;
1559 } else
1560 RxContext->InformationToReturn = len;
1561 }
1562 else {
1565 print_wait_status(0, "[upcall]", status, NULL, NULL, 0);
1566 switch (status) {
1567 case STATUS_SUCCESS: goto process_upcall;
1568 case STATUS_USER_APC:
1569 case STATUS_ALERTED:
1570 default: goto out;
1571 }
1572 }
1573out:
1574 return status;
1575}
1576
1579 unsigned char **buf)
1580{
1582
1583 RtlCopyMemory(&tmp->xid, *buf, sizeof(tmp->xid));
1584 *buf += sizeof(tmp->xid);
1585 RtlCopyMemory(&tmp->opcode, *buf, sizeof(tmp->opcode));
1586 *buf += sizeof(tmp->opcode);
1587 RtlCopyMemory(&tmp->status, *buf, sizeof(tmp->status));
1588 *buf += sizeof(tmp->status);
1589 RtlCopyMemory(&tmp->errno, *buf, sizeof(tmp->errno));
1590 *buf += sizeof(tmp->errno);
1591#ifdef DEBUG_MARSHAL_HEADER
1592 DbgP("[downcall header] xid=%lld opcode=%s status=%d errno=%d\n", tmp->xid,
1593 opcode2string(tmp->opcode), tmp->status, tmp->errno);
1594#endif
1595}
1596
1599 unsigned char **buf)
1600{
1601 RtlCopyMemory(&cur->session, *buf, sizeof(HANDLE));
1602 *buf += sizeof(HANDLE);
1603 RtlCopyMemory(&cur->version, *buf, sizeof(DWORD));
1604 *buf += sizeof(DWORD);
1605 RtlCopyMemory(&cur->u.Mount.lease_time, *buf, sizeof(DWORD));
1606 *buf += sizeof(DWORD);
1607 RtlCopyMemory(cur->u.Mount.FsAttrs, *buf, sizeof(FILE_FS_ATTRIBUTE_INFORMATION));
1608#ifdef DEBUG_MARSHAL_DETAIL
1609 DbgP("unmarshal_nfs41_mount: session pointer 0x%x version %d lease_time "
1610 "%d\n", cur->session, cur->version, cur->u.Mount.lease_time);
1611#endif
1612}
1613
1616 PULONGLONG dest_buf,
1617 unsigned char **buf)
1618{
1619 RtlCopyMemory(dest_buf, *buf, sizeof(ULONGLONG));
1620#ifdef DEBUG_MARSHAL_DETAIL
1621 DbgP("unmarshal_nfs41_setattr: returned ChangeTime %llu\n", *dest_buf);
1622#endif
1623}
1624
1627 unsigned char **buf)
1628{
1630
1631 RtlCopyMemory(&cur->buf_len, *buf, sizeof(cur->buf_len));
1632 *buf += sizeof(cur->buf_len);
1633 RtlCopyMemory(&cur->ChangeTime, *buf, sizeof(ULONGLONG));
1634#ifdef DEBUG_MARSHAL_DETAIL
1635 DbgP("unmarshal_nfs41_rw: returned len %lu ChangeTime %llu\n",
1636 cur->buf_len, cur->ChangeTime);
1637#endif
1638#if 1
1639 /* 08/27/2010: it looks like we really don't need to call
1640 * MmUnmapLockedPages() eventhough we called
1641 * MmMapLockedPagesSpecifyCache() as the MDL passed to us
1642 * is already locked.
1643 */
1644 _SEH2_TRY {
1645 MmUnmapLockedPages(cur->buf, cur->u.ReadWrite.MdlAddress);
1647 NTSTATUS code;
1649 print_error("Call to MmUnmapLockedPages failed due to"
1650 " exception 0x%0x\n", code);
1652 } _SEH2_END;
1653#endif
1654 return status;
1655}
1656
1659 unsigned char **buf)
1660{
1662
1663 _SEH2_TRY {
1664 if (cur->u.Open.EaBuffer)
1665 MmUnmapLockedPages(cur->u.Open.EaBuffer, cur->u.Open.EaMdl);
1667 print_error("MmUnmapLockedPages thrown exception=0x%0x\n", _SEH2_GetExceptionCode());
1668 status = cur->status = STATUS_ACCESS_DENIED;
1669 goto out;
1670 } _SEH2_END;
1671
1672 RtlCopyMemory(&cur->u.Open.binfo, *buf, sizeof(FILE_BASIC_INFORMATION));
1673 *buf += sizeof(FILE_BASIC_INFORMATION);
1674 RtlCopyMemory(&cur->u.Open.sinfo, *buf, sizeof(FILE_STANDARD_INFORMATION));
1675 *buf += sizeof(FILE_STANDARD_INFORMATION);
1676 RtlCopyMemory(&cur->open_state, *buf, sizeof(HANDLE));
1677 *buf += sizeof(HANDLE);
1678 RtlCopyMemory(&cur->u.Open.mode, *buf, sizeof(DWORD));
1679 *buf += sizeof(DWORD);
1680 RtlCopyMemory(&cur->ChangeTime, *buf, sizeof(ULONGLONG));
1681 *buf += sizeof(ULONGLONG);
1682 RtlCopyMemory(&cur->u.Open.deleg_type, *buf, sizeof(DWORD));
1683 *buf += sizeof(DWORD);
1684 if (cur->errno == ERROR_REPARSE) {
1685 RtlCopyMemory(&cur->u.Open.symlink_embedded, *buf, sizeof(BOOLEAN));
1686 *buf += sizeof(BOOLEAN);
1687 RtlCopyMemory(&cur->u.Open.symlink.MaximumLength, *buf,
1688 sizeof(USHORT));
1689 *buf += sizeof(USHORT);
1690 cur->u.Open.symlink.Length = cur->u.Open.symlink.MaximumLength -
1691 sizeof(WCHAR);
1692 cur->u.Open.symlink.Buffer = RxAllocatePoolWithTag(NonPagedPool,
1693 cur->u.Open.symlink.MaximumLength, NFS41_MM_POOLTAG);
1694 if (cur->u.Open.symlink.Buffer == NULL) {
1697 goto out;
1698 }
1699 RtlCopyMemory(cur->u.Open.symlink.Buffer, *buf,
1700 cur->u.Open.symlink.MaximumLength);
1701#ifdef DEBUG_MARSHAL_DETAIL
1702 DbgP("unmarshal_nfs41_open: ERROR_REPARSE -> '%wZ'\n", &cur->u.Open.symlink);
1703#endif
1704 }
1705#ifdef DEBUG_MARSHAL_DETAIL
1706 DbgP("unmarshal_nfs41_open: open_state 0x%x mode %o changeattr %llu "
1707 "deleg_type %d\n", cur->open_state, cur->u.Open.mode,
1708 cur->ChangeTime, cur->u.Open.deleg_type);
1709#endif
1710out:
1711 return status;
1712}
1713
1716 unsigned char **buf)
1717{
1719 ULONG buf_len;
1720
1721 RtlCopyMemory(&buf_len, *buf, sizeof(ULONG));
1722#ifdef DEBUG_MARSHAL_DETAIL
1723 DbgP("unmarshal_nfs41_dirquery: reply size %d\n", buf_len);
1724#endif
1725 *buf += sizeof(ULONG);
1726 _SEH2_TRY {
1727 MmUnmapLockedPages(cur->u.QueryFile.mdl_buf, cur->u.QueryFile.mdl);
1729 NTSTATUS code;
1731 print_error("MmUnmapLockedPages thrown exception=0x%0x\n", code);
1733 } _SEH2_END;
1734 if (buf_len > cur->buf_len)
1735 cur->status = STATUS_BUFFER_TOO_SMALL;
1736 cur->buf_len = buf_len;
1737
1738 return status;
1739}
1740
1743 PVOID attr_value,
1744 ULONG *attr_len,
1745 unsigned char **buf)
1746{
1747 ULONG buf_len;
1748 RtlCopyMemory(&buf_len, *buf, sizeof(ULONG));
1749 if (buf_len > *attr_len) {
1750 cur->status = STATUS_BUFFER_TOO_SMALL;
1751 return;
1752 }
1753 *buf += sizeof(ULONG);
1754 *attr_len = buf_len;
1755 RtlCopyMemory(attr_value, *buf, buf_len);
1756 *buf += buf_len;
1757}
1758
1761 unsigned char **buf)
1762{
1763 RtlCopyMemory(&cur->u.QueryEa.Overflow, *buf, sizeof(ULONG));
1764 *buf += sizeof(ULONG);
1765 RtlCopyMemory(&cur->buf_len, *buf, sizeof(ULONG));
1766 *buf += sizeof(ULONG);
1767 if (cur->u.QueryEa.Overflow != ERROR_INSUFFICIENT_BUFFER) {
1768 RtlCopyMemory(cur->buf, *buf, cur->buf_len);
1769 *buf += cur->buf_len;
1770 }
1771}
1772
1775 unsigned char **buf)
1776{
1777 unmarshal_nfs41_attrget(cur, cur->buf, &cur->buf_len, buf);
1778 RtlCopyMemory(&cur->ChangeTime, *buf, sizeof(LONGLONG));
1779#ifdef DEBUG_MARSHAL_DETAIL
1780 if (cur->u.QueryFile.InfoClass == FileBasicInformation)
1781 DbgP("[unmarshal_nfs41_getattr] ChangeTime %llu\n", cur->ChangeTime);
1782#endif
1783}
1784
1787 unsigned char **buf)
1788{
1790 DWORD buf_len;
1791
1792 RtlCopyMemory(&buf_len, *buf, sizeof(DWORD));
1793 *buf += sizeof(DWORD);
1795 buf_len, NFS41_MM_POOLTAG_ACL);
1796 if (cur->buf == NULL) {
1798 goto out;
1799 }
1800 RtlCopyMemory(cur->buf, *buf, buf_len);
1801 if (buf_len > cur->buf_len)
1802 cur->status = STATUS_BUFFER_TOO_SMALL;
1803 cur->buf_len = buf_len;
1804
1805out:
1806 return status;
1807}
1808
1811 unsigned char **buf)
1812{
1813 if (cur->u.Symlink.set) return;
1814
1815 RtlCopyMemory(&cur->u.Symlink.target->Length, *buf, sizeof(USHORT));
1816 *buf += sizeof(USHORT);
1817 if (cur->u.Symlink.target->Length >
1818 cur->u.Symlink.target->MaximumLength) {
1819 cur->status = STATUS_BUFFER_TOO_SMALL;
1820 return;
1821 }
1822 RtlCopyMemory(cur->u.Symlink.target->Buffer, *buf,
1823 cur->u.Symlink.target->Length);
1824 cur->u.Symlink.target->Length -= sizeof(UNICODE_NULL);
1825}
1826
1828 IN PRX_CONTEXT RxContext)
1829{
1831 PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
1832 ULONG in_len = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
1833 unsigned char *buf = LowIoContext->ParamsFor.IoCtl.pInputBuffer;
1836 BOOLEAN found = 0;
1837
1838 print_hexbuf(0, (unsigned char *)"downcall buffer", buf, in_len);
1839
1842 if (tmp == NULL) goto out;
1843
1845
1847 pEntry = &downcall.head;
1848 pEntry = pEntry->Flink;
1849 while (pEntry != NULL) {
1852 if (cur->xid == tmp->xid) {
1853 found = 1;
1854 break;
1855 }
1856 if (pEntry->Flink == &downcall.head)
1857 break;
1858 pEntry = pEntry->Flink;
1859 }
1862 if (!found) {
1863 print_error("Didn't find xid=%lld entry\n", tmp->xid);
1864 goto out_free;
1865 }
1866
1867 ExAcquireFastMutex(&cur->lock);
1868 if (cur->state == NFS41_NOT_WAITING) {
1869 DbgP("[downcall] Nobody is waiting for this request!!!\n");
1870 switch(cur->opcode) {
1871 case NFS41_WRITE:
1872 case NFS41_READ:
1873 MmUnmapLockedPages(cur->buf, cur->u.ReadWrite.MdlAddress);
1874 break;
1875 case NFS41_DIR_QUERY:
1876 MmUnmapLockedPages(cur->u.QueryFile.mdl_buf,
1877 cur->u.QueryFile.mdl);
1878 IoFreeMdl(cur->u.QueryFile.mdl);
1879 break;
1880 case NFS41_OPEN:
1881 if (cur->u.Open.EaMdl) {
1882 MmUnmapLockedPages(cur->u.Open.EaBuffer,
1883 cur->u.Open.EaMdl);
1884 IoFreeMdl(cur->u.Open.EaMdl);
1885 }
1886 break;
1887 }
1888 ExReleaseFastMutex(&cur->lock);
1890 RxFreePool(cur);
1892 goto out_free;
1893 }
1894 cur->state = NFS41_DONE_PROCESSING;
1895 cur->status = tmp->status;
1896 cur->errno = tmp->errno;
1898
1899 if (!tmp->status) {
1900 switch (tmp->opcode) {
1901 case NFS41_MOUNT:
1903 break;
1904 case NFS41_WRITE:
1905 case NFS41_READ:
1907 break;
1908 case NFS41_OPEN:
1910 break;
1911 case NFS41_DIR_QUERY:
1913 break;
1914 case NFS41_FILE_QUERY:
1916 break;
1917 case NFS41_EA_GET:
1919 break;
1920 case NFS41_SYMLINK:
1922 break;
1923 case NFS41_VOLUME_QUERY:
1924 unmarshal_nfs41_attrget(cur, cur->buf, &cur->buf_len, &buf);
1925 break;
1926 case NFS41_ACL_QUERY:
1928 break;
1929 case NFS41_FILE_SET:
1930 unmarshal_nfs41_setattr(cur, &cur->ChangeTime, &buf);
1931 break;
1932 case NFS41_EA_SET:
1933 unmarshal_nfs41_setattr(cur, &cur->ChangeTime, &buf);
1934 break;
1935 case NFS41_ACL_SET:
1936 unmarshal_nfs41_setattr(cur, &cur->ChangeTime, &buf);
1937 break;
1938 }
1939 }
1940 ExReleaseFastMutex(&cur->lock);
1941 if (cur->async_op) {
1942 if (cur->status == STATUS_SUCCESS) {
1943 cur->u.ReadWrite.rxcontext->StoredStatus = STATUS_SUCCESS;
1944 cur->u.ReadWrite.rxcontext->InformationToReturn =
1945 cur->buf_len;
1946 } else {
1947 cur->u.ReadWrite.rxcontext->StoredStatus =
1948 map_readwrite_errors(cur->status);
1949 cur->u.ReadWrite.rxcontext->InformationToReturn = 0;
1950 }
1952 RxLowIoCompletion(cur->u.ReadWrite.rxcontext);
1953 RxFreePool(cur);
1954 } else
1955 KeSetEvent(&cur->cond, 0, FALSE);
1956
1957out_free:
1958 RxFreePool(tmp);
1959out:
1960 return status;
1961}
1962
1964 DWORD version)
1965{
1968
1969 DbgEn();
1972 if (status) goto out;
1973
1975 SeDeleteClientSecurity(&entry->sec_ctx);
1976 if (status) goto out;
1977
1979out:
1980 DbgEx();
1981 return status;
1982}
1983
1985 OUT PHANDLE phSection)
1986{
1989 UNICODE_STRING SectionName;
1990 SECURITY_DESCRIPTOR SecurityDesc;
1991 OBJECT_ATTRIBUTES SectionAttrs;
1992 LARGE_INTEGER nSectionSize;
1993
1994 DbgEn();
1995
1997
1998 /* XXX: setting dacl=NULL grants access to everyone */
1999 status = RtlCreateSecurityDescriptor(&SecurityDesc,
2001 if (status) {
2002 print_error("RtlCreateSecurityDescriptor() failed with %08X\n", status);
2003 goto out;
2004 }
2006 if (status) {
2007 print_error("RtlSetDaclSecurityDescriptor() failed with %08X\n", status);
2008 goto out;
2009 }
2010
2011 InitializeObjectAttributes(&SectionAttrs, &SectionName,
2012 0, NULL, &SecurityDesc);
2013
2014 nSectionSize.QuadPart = sizeof(NFS41NP_SHARED_MEMORY);
2015
2016 status = ZwCreateSection(&hSection, SECTION_MAP_READ | SECTION_MAP_WRITE,
2017 &SectionAttrs, &nSectionSize, PAGE_READWRITE, SEC_COMMIT, NULL);
2018 switch (status) {
2019 case STATUS_SUCCESS:
2020 break;
2022 DbgP("section already created; returning success\n");
2024 goto out;
2025 default:
2026 DbgP("ZwCreateSection failed with %08X\n", status);
2027 goto out;
2028 }
2029out:
2030 DbgEx();
2031 return status;
2032}
2033
2036{
2038 DbgEn();
2040 DbgEx();
2041 return status;
2042}
2043
2044#ifdef __REACTOS__
2046#else
2048#endif
2049 IN OUT PRX_CONTEXT RxContext,
2051{
2053 NFS41GetDeviceExtension(RxContext, DevExt);
2054
2055 DbgEn();
2056
2057 status = SharedMemoryInit(&DevExt->SharedMemorySection);
2058 if (status) {
2059 print_error("InitSharedMemory failed with %08X\n", status);
2061 goto out;
2062 }
2063
2067out:
2068 DbgEx();
2069 return status;
2070}
2071
2072#ifdef __REACTOS__
2074#else
2076#endif
2077 IN OUT PRX_CONTEXT RxContext,
2079{
2081 NFS41GetDeviceExtension(RxContext, DevExt);
2082 DbgEn();
2083 status = SharedMemoryFree(DevExt->SharedMemorySection);
2084 DbgEx();
2085 return status;
2086}
2087
2089 IN PUNICODE_STRING ConnectionName,
2093{
2097
2098#ifdef DEBUG_MOUNT
2099 DbgEn();
2100#endif
2103
2104 print_error("Len %d Buf %p\n", EaLength, EaBuffer);
2105
2106 status = ZwCreateFile(Handle, SYNCHRONIZE, &ObjectAttributes,
2112
2113#ifdef DEBUG_MOUNT
2114 DbgEx();
2115#endif
2116 return status;
2117}
2118
2120 IN PVOID Buffer,
2121 IN ULONG BufferLen,
2122 OUT PUNICODE_STRING pConnectionName,
2123 OUT PVOID *ppEaBuffer,
2124 OUT PULONG pEaLength)
2125{
2127 USHORT NameLength, EaPadding;
2128 ULONG EaLength, BufferLenExpected;
2129 PBYTE ptr;
2130
2131 /* make sure buffer is at least big enough for header */
2132 if (BufferLen < sizeof(USHORT) + sizeof(USHORT) + sizeof(ULONG)) {
2134 print_error("Invalid input buffer.\n");
2135 pConnectionName->Length = pConnectionName->MaximumLength = 0;
2136 *ppEaBuffer = NULL;
2137 *pEaLength = 0;
2138 goto out;
2139 }
2140
2141 ptr = Buffer;
2142 NameLength = *(PUSHORT)ptr;
2143 ptr += sizeof(USHORT);
2144 EaPadding = *(PUSHORT)ptr;
2145 ptr += sizeof(USHORT);
2146 EaLength = *(PULONG)ptr;
2147 ptr += sizeof(ULONG);
2148
2149 /* validate buffer length */
2150 BufferLenExpected = sizeof(USHORT) + sizeof(USHORT) + sizeof(ULONG) +
2151 NameLength + EaPadding + EaLength;
2152 if (BufferLen != BufferLenExpected) {
2154 print_error("Received buffer of length %lu, but expected %lu bytes.\n",
2155 BufferLen, BufferLenExpected);
2156 pConnectionName->Length = pConnectionName->MaximumLength = 0;
2157 *ppEaBuffer = NULL;
2158 *pEaLength = 0;
2159 goto out;
2160 }
2161
2162 pConnectionName->Buffer = (PWCH)ptr;
2163 pConnectionName->Length = NameLength - sizeof(WCHAR);
2164 pConnectionName->MaximumLength = NameLength;
2165
2166 if (EaLength)
2167 *ppEaBuffer = ptr + NameLength + EaPadding;
2168 else
2169 *ppEaBuffer = NULL;
2170 *pEaLength = EaLength;
2171
2172out:
2173 return status;
2174}
2175
2177 IN PRX_CONTEXT RxContext,
2178 OUT PBOOLEAN PostToFsp)
2179{
2182 PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
2184 ULONG BufferLen = LowIoContext->ParamsFor.IoCtl.InputBufferLength, EaLength;
2186 BOOLEAN Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
2187
2188#ifdef DEBUG_MOUNT
2189 DbgEn();
2190#endif
2191
2192 if (!Wait) {
2193 //just post right now!
2194 DbgP("returning STATUS_PENDING\n");
2195 *PostToFsp = TRUE;
2197 goto out;
2198 }
2199
2202 if (status != STATUS_SUCCESS)
2203 goto out;
2204
2207 ZwClose(Handle);
2208out:
2209#ifdef DEBUG_MOUNT
2210 DbgEx();
2211#endif
2212 return status;
2213}
2214
2215#ifdef ENABLE_TIMINGS
2216void print_op_stat(
2217 const char *op_str,
2218 nfs41_timings *time, BOOLEAN clear)
2219{
2220 DbgP("%-9s: num_ops=%-10d delta_ticks=%-10d size=%-10d\n", op_str,
2221 time->tops, time->tops ? time->ticks/time->tops : 0,
2222 time->sops ? time->size/time->sops : 0);
2223 if (clear) {
2224 time->tops = 0;
2225 time->ticks = 0;
2226 time->size = 0;
2227 time->sops = 0;
2228 }
2229}
2230#endif
2233 DWORD version,
2234 DWORD timeout)
2235{
2238
2239#ifdef DEBUG_MOUNT
2240 DbgEn();
2241#endif
2244 SeDeleteClientSecurity(&entry->sec_ctx);
2245 if (status) goto out;
2246
2249out:
2250#ifdef ENABLE_TIMINGS
2251 print_op_stat("lookup", &lookup, 1);
2252 print_op_stat("open", &open, 1);
2253 print_op_stat("close", &close, 1);
2254 print_op_stat("volume", &volume, 1);
2255 print_op_stat("getattr", &getattr, 1);
2256 print_op_stat("setattr", &setattr, 1);
2257 print_op_stat("getexattr", &getexattr, 1);
2258 print_op_stat("setexattr", &setexattr, 1);
2259 print_op_stat("readdir", &readdir, 1);
2260 print_op_stat("getacl", &getacl, 1);
2261 print_op_stat("setacl", &setacl, 1);
2262 print_op_stat("read", &read, 1);
2263 print_op_stat("write", &write, 1);
2264 print_op_stat("lock", &lock, 1);
2265 print_op_stat("unlock", &unlock, 1);
2266#endif
2267#ifdef DEBUG_MOUNT
2268 DbgEx();
2269#endif
2270 return status;
2271}
2272
2274 IN PRX_CONTEXT RxContext,
2275 OUT PBOOLEAN PostToFsp)
2276{
2278 PLOWIO_CONTEXT LowIoContext = &RxContext->LowIoContext;
2279 PWCHAR ConnectName = LowIoContext->ParamsFor.IoCtl.pInputBuffer;
2280 ULONG ConnectNameLen = LowIoContext->ParamsFor.IoCtl.InputBufferLength;
2281 HANDLE Handle;
2283 PFILE_OBJECT pFileObject;
2284 BOOLEAN Wait = BooleanFlagOn(RxContext->Flags, RX_CONTEXT_FLAG_WAIT);
2285
2286#ifdef DEBUG_MOUNT
2287 DbgEn();
2288#endif
2289
2290 if (!Wait) {
2291 //just post right now!
2292 *PostToFsp = TRUE;
2293 DbgP("returning STATUS_PENDING\n");
2295 goto out;
2296 }
2297
2298 FileName.Buffer = ConnectName;
2299 FileName.Length = (USHORT) ConnectNameLen - sizeof(WCHAR);
2300 FileName.MaximumLength = (USHORT) ConnectNameLen;
2301
2303 if (status != STATUS_SUCCESS)
2304 goto out;
2305
2307 (PVOID *)&pFileObject, NULL);
2308 if (NT_SUCCESS(status)) {
2309 PV_NET_ROOT VNetRoot;
2310
2311 // VNetRoot exists as FOBx in the FsContext2
2312 VNetRoot = (PV_NET_ROOT) pFileObject->FsContext2;
2313 // make sure the node looks right
2314 if (NodeType(VNetRoot) == RDBSS_NTC_V_NETROOT)
2315 {
2316#ifdef DEBUG_MOUNT
2317 DbgP("Calling RxFinalizeConnection for NetRoot %p from VNetRoot %p\n",
2318 VNetRoot->NetRoot, VNetRoot);
2319#endif
2320 status = RxFinalizeConnection(VNetRoot->NetRoot, VNetRoot, TRUE);
2321 }
2322 else
2324
2325 ObDereferenceObject(pFileObject);
2326 }
2327 ZwClose(Handle);
2328out:
2329#ifdef DEBUG_MOUNT
2330 DbgEx();
2331#endif
2332 return status;
2333}
2334
2335#ifdef __REACTOS__
2337#else
2339#endif
2340 IN OUT PRX_CONTEXT RxContext)
2341{
2343 UCHAR op = RxContext->MajorFunction;
2344 PLOWIO_CONTEXT io_ctx = &RxContext->LowIoContext;
2345 ULONG fsop = io_ctx->ParamsFor.FsCtl.FsControlCode, state;
2346 ULONG in_len = io_ctx->ParamsFor.IoCtl.InputBufferLength;
2348 NFS41GetDeviceExtension(RxContext, DevExt);
2349 DWORD nfs41d_version = 0;
2350
2351 //DbgEn();
2352
2353 print_ioctl(0, op);
2354 switch(op) {
2357 break;
2360 print_fs_ioctl(0, fsop);
2361 switch (fsop) {
2363 nfs41_invalidate_cache(RxContext);
2365 break;
2366 case IOCTL_NFS41_READ:
2367 status = nfs41_upcall(RxContext);
2368 break;
2369 case IOCTL_NFS41_WRITE:
2370 status = nfs41_downcall(RxContext);
2371 break;
2373 status = nfs41_CreateConnection(RxContext, &RxContext->PostRequest);
2374 break;
2376 if (RxContext->RxDeviceObject->NumberOfActiveFcbs > 0) {
2377 DbgP("device has open handles %d\n",
2378 RxContext->RxDeviceObject->NumberOfActiveFcbs);
2379#ifdef __REACTOS__
2380 if (RxContext->RxDeviceObject->pRxNetNameTable != NULL)
2381 {
2382#define DUMP_FCB_TABLE_FROM_NETROOT(N) \
2383{ \
2384 USHORT Bucket2; \
2385 BOOLEAN Release2 = FALSE; \
2386 if (!RxIsFcbTableLockAcquired(&(N)->FcbTable)) \
2387 { \
2388 RxAcquireFcbTableLockExclusive(&(N)->FcbTable, TRUE); \
2389 Release2 = TRUE; \
2390 } \
2391 for (Bucket2 = 0; Bucket2 < (N)->FcbTable.NumberOfBuckets; ++Bucket2) \
2392 { \
2393 PLIST_ENTRY Entry2; \
2394 for (Entry2 = (N)->FcbTable.HashBuckets[Bucket2].Flink; \
2395 Entry2 != &(N)->FcbTable.HashBuckets[Bucket2]; \
2396 Entry2 = Entry2->Flink) \
2397 { \
2398 PFCB Fcb; \
2399 Fcb = CONTAINING_RECORD(Entry2, FCB, FcbTableEntry.HashLinks); \
2400 DbgP("Fcb: %p still has %d references\n", Fcb, Fcb->NodeReferenceCount); \
2401 DbgP("It is for: %wZ\n", &Fcb->FcbTableEntry.Path); \
2402 } \
2403 } \
2404 if (Release2) \
2405 { \
2406 RxReleaseFcbTableLock(&(N)->FcbTable); \
2407 } \
2408}
2409 USHORT Bucket;
2411
2412 if (!RxIsPrefixTableLockAcquired(RxContext->RxDeviceObject->pRxNetNameTable))
2413 {
2414 RxAcquirePrefixTableLockExclusive(RxContext->RxDeviceObject->pRxNetNameTable, TRUE);
2415 Release = TRUE;
2416 }
2417
2418 for (Bucket = 0; Bucket < RxContext->RxDeviceObject->pRxNetNameTable->TableSize; ++Bucket)
2419 {
2421
2422 for (Entry = RxContext->RxDeviceObject->pRxNetNameTable->HashBuckets[Bucket].Flink;
2423 Entry != &RxContext->RxDeviceObject->pRxNetNameTable->HashBuckets[Bucket];
2424 Entry = Entry->Flink)
2425 {
2426 PVOID Container;
2427
2428 Container = CONTAINING_RECORD(Entry, RX_PREFIX_ENTRY, HashLinks)->ContainingRecord;
2429 switch (NodeType(Container) & ~RX_SCAVENGER_MASK)
2430 {
2431 case RDBSS_NTC_NETROOT:
2432 {
2433 PNET_ROOT NetRoot;
2434
2435 NetRoot = Container;
2436 DUMP_FCB_TABLE_FROM_NETROOT(NetRoot);
2437 break;
2438 }
2439
2441 {
2442 PV_NET_ROOT VNetRoot;
2443
2444 VNetRoot = Container;
2445 if (VNetRoot->NetRoot != NULL)
2446 {
2447 PNET_ROOT NetRoot;
2448
2449 NetRoot = VNetRoot->NetRoot;
2450 DUMP_FCB_TABLE_FROM_NETROOT(NetRoot);
2451 }
2452 break;
2453 }
2454
2455 default:
2456 {
2457 DbgP("Other node found: %x\n", NodeType(Container));
2458 break;
2459 }
2460 }
2461 }
2462 }
2463
2464 if (Release)
2465 {
2466 RxReleasePrefixTableLock(RxContext->RxDeviceObject->pRxNetNameTable);
2467 }
2468#undef DUMP_FCB_TABLE_FROM_NETROOT
2469 }
2470 else
2471 {
2472 DbgP("RxNetNameTable is NULL for: %p\n", RxContext->RxDeviceObject);
2473 }
2474#endif
2476 break;
2477 }
2478 status = nfs41_DeleteConnection(RxContext, &RxContext->PostRequest);
2479 break;
2482
2483 if (io_ctx->ParamsFor.IoCtl.OutputBufferLength >= sizeof(ULONG)) {
2484 // map the states to control app's equivalents
2486 switch (nfs41_start_state) {
2490 break;
2493 break;
2496 break;
2497 }
2498 *(ULONG *)io_ctx->ParamsFor.IoCtl.pOutputBuffer = state;
2499 RxContext->InformationToReturn = sizeof(ULONG);
2501 } else
2503 break;
2504 case IOCTL_NFS41_START:
2506 if (in_len >= sizeof(DWORD)) {
2507 RtlCopyMemory(&nfs41d_version, buf, sizeof(DWORD));
2508 DbgP("NFS41 Daemon sent start request with version %d\n",
2509 nfs41d_version);
2510 DbgP("Currently used NFS41 Daemon version is %d\n",
2511 DevExt->nfs41d_version);
2512 DevExt->nfs41d_version = nfs41d_version;
2513 }
2514 switch(nfs41_start_state) {
2520 //lack of break is intentional
2522 status = RxStartMinirdr(RxContext, &RxContext->PostRequest);
2524 DbgP("redirector started\n");
2526 } else if (status == STATUS_PENDING &&
2527 RxContext->PostRequest == TRUE) {
2528 DbgP("RxStartMinirdr pending %08lx\n", status);
2530 }
2531 break;
2534 break;
2535 default:
2537 }
2538 break;
2539 case IOCTL_NFS41_STOP:
2541 nfs41_shutdown_daemon(DevExt->nfs41d_version);
2542 if (RxContext->RxDeviceObject->NumberOfActiveFcbs > 0) {
2543 DbgP("device has open handles %d\n",
2544 RxContext->RxDeviceObject->NumberOfActiveFcbs);
2546 break;
2547 }
2548
2553
2554 status = RxStopMinirdr(RxContext, &RxContext->PostRequest);
2555 DbgP("RxStopMinirdr status %08lx\n", status);
2556 if (status == STATUS_PENDING && RxContext->PostRequest == TRUE )
2558 break;
2559 default:
2561 };
2562 break;
2563 default:
2565 };
2566
2567 //DbgEx();
2568 return status;
2569}
2570
2571#ifndef __REACTOS__
2573 PMRX_SRVCALL_CALLBACK_CONTEXT pCallbackContext)
2574{
2575#else
2577 PVOID pContext)
2578{
2579 PMRX_SRVCALL_CALLBACK_CONTEXT pCallbackContext = pContext;
2580#endif
2582 PMRX_SRVCALL_CALLBACK_CONTEXT SCCBC = pCallbackContext;
2583 PMRX_SRV_CALL pSrvCall;
2584 PMRX_SRVCALLDOWN_STRUCTURE SrvCalldownStructure =
2586 PNFS41_SERVER_ENTRY pServerEntry = NULL;
2587
2588#ifdef DEBUG_MOUNT
2589 DbgEn();
2590#endif
2591
2592 pSrvCall = SrvCalldownStructure->SrvCall;
2593
2594 ASSERT( pSrvCall );
2595 ASSERT( NodeType(pSrvCall) == RDBSS_NTC_SRVCALL );
2596 print_srv_call(0, pSrvCall);
2597
2598 // validate the server name with the test name of 'pnfs'
2599#ifdef DEBUG_MOUNT
2600 DbgP("SrvCall: Connection Name Length: %d %wZ\n",
2601 pSrvCall->pSrvCallName->Length, pSrvCall->pSrvCallName);
2602#endif
2603
2604 if (pSrvCall->pSrvCallName->Length > SERVER_NAME_BUFFER_SIZE) {
2605 print_error("Server name '%wZ' too long for server entry (max %u)\n",
2608 goto out;
2609 }
2610
2611 /* Let's create our own representation of the server */
2614 if (pServerEntry == NULL) {
2616 goto out;
2617 }
2618 RtlZeroMemory(pServerEntry, sizeof(NFS41_SERVER_ENTRY));
2619
2620 pServerEntry->Name.Buffer = pServerEntry->NameBuffer;
2621 pServerEntry->Name.Length = pSrvCall->pSrvCallName->Length;
2623 RtlCopyMemory(pServerEntry->Name.Buffer, pSrvCall->pSrvCallName->Buffer,
2624 pServerEntry->Name.Length);
2625
2626 pCallbackContext->RecommunicateContext = pServerEntry;
2627#ifdef __REACTOS__
2628 InterlockedExchangePointer((void * volatile *)&pServerEntry->pRdbssSrvCall, pSrvCall);
2629#else
2630 InterlockedExchangePointer(&pServerEntry->pRdbssSrvCall, pSrvCall);
2631#endif
2632
2633out:
2634 SCCBC->Status = status;
2635 SrvCalldownStructure->CallBack(SCCBC);
2636
2637#ifdef DEBUG_MOUNT
2638 DbgEx();
2639#endif
2640 return status;
2641}
2642
2643#ifdef __REACTOS__
2644VOID NTAPI _nfs41_CreateSrvCall_v(
2645 PVOID pCallbackContext)
2646{
2647 _nfs41_CreateSrvCall(pCallbackContext);
2648}
2649#endif
2650
2651#ifdef __REACTOS__
2653#else
2655#endif
2656 PMRX_SRV_CALL pSrvCall,
2657 PMRX_SRVCALL_CALLBACK_CONTEXT pCallbackContext)
2658{
2660
2661 ASSERT( pSrvCall );
2662 ASSERT( NodeType(pSrvCall) == RDBSS_NTC_SRVCALL );
2663
2665 DbgP("executing with RDBSS context\n");
2666 status = _nfs41_CreateSrvCall(pCallbackContext);
2667 } else {
2669#ifdef __REACTOS__
2670 _nfs41_CreateSrvCall_v, pCallbackContext);
2671#else
2672 _nfs41_CreateSrvCall, pCallbackContext);
2673#endif
2674 if (status != STATUS_SUCCESS) {
2675 print_error("RxDispatchToWorkerThread returned status %08lx\n",
2676 status);
2677 pCallbackContext->Status = status;
2678 pCallbackContext->SrvCalldownStructure->CallBack(pCallbackContext);
2680 }
2681 }
2682 /* RDBSS expects MRxCreateSrvCall to return STATUS_PENDING */
2683 if (status == STATUS_SUCCESS)
2685
2686 return status;
2687}
2688
2689#ifdef __REACTOS__
2691#else
2693#endif
2694 IN OUT PMRX_SRV_CALL pSrvCall,
2695 IN BOOLEAN ThisMinirdrIsTheWinner,
2696 IN OUT PVOID pSrvCallContext)
2697{
2699 PNFS41_SERVER_ENTRY pServerEntry;
2700
2701 pServerEntry = (PNFS41_SERVER_ENTRY)pSrvCallContext;
2702
2703 if (!ThisMinirdrIsTheWinner) {
2704 ASSERT(1);
2705 goto out;
2706 }
2707
2708 pSrvCall->Context = pServerEntry;
2709out:
2710 return status;
2711}
2712
2714 DWORD status)
2715{
2716 switch (status) {
2717 case NO_ERROR: return STATUS_SUCCESS;
2722 default:
2723 print_error("failed to map windows error %d to NTSTATUS; "
2724 "defaulting to STATUS_INSUFFICIENT_RESOURCES\n", status);
2726 }
2727}
2728
2733 DWORD *version,
2735{
2738
2739#ifdef DEBUG_MOUNT
2740 DbgEn();
2741 DbgP("Server Name %wZ Mount Point %wZ SecFlavor %d\n",
2742 &config->SrvName, &config->MntPt, sec_flavor);
2743#endif
2746 if (status) goto out;
2747
2748 entry->u.Mount.srv_name = &config->SrvName;
2749 entry->u.Mount.root = &config->MntPt;
2750 entry->u.Mount.rsize = config->ReadSize;
2751 entry->u.Mount.wsize = config->WriteSize;
2752 entry->u.Mount.sec_flavor = sec_flavor;
2753 entry->u.Mount.FsAttrs = FsAttrs;
2754
2756 SeDeleteClientSecurity(&entry->sec_ctx);
2757 if (status) goto out;
2758 *session = entry->session;
2759 if (entry->u.Mount.lease_time > config->timeout)
2760 config->timeout = entry->u.Mount.lease_time;
2761
2762 /* map windows ERRORs to NTSTATUS */
2763 status = map_mount_errors(entry->status);
2764 if (status == STATUS_SUCCESS)
2765 *version = entry->version;
2767out:
2768#ifdef DEBUG_MOUNT
2769 DbgEx();
2770#endif
2771 return status;
2772}
2773
2774/* TODO: move mount config stuff to another file -cbodley */
2775
2778{
2780
2783 Config->ReadOnly = FALSE;
2784 Config->write_thru = FALSE;
2785 Config->nocache = FALSE;
2786 Config->SrvName.Length = 0;
2787 Config->SrvName.MaximumLength = SERVER_NAME_BUFFER_SIZE;
2788 Config->SrvName.Buffer = Config->srv_buffer;
2789 Config->MntPt.Length = 0;
2790 Config->MntPt.MaximumLength = MAX_PATH;
2791 Config->MntPt.Buffer = Config->mntpt_buffer;
2792 Config->SecFlavor.Length = 0;
2793 Config->SecFlavor.MaximumLength = MAX_SEC_FLAVOR_LEN;
2794 Config->SecFlavor.Buffer = Config->sec_flavor;
2795 RtlCopyUnicodeString(&Config->SecFlavor, &AUTH_SYS_NAME);
2796 Config->timeout = UPCALL_TIMEOUT_DEFAULT;
2797}
2798
2801 IN PUNICODE_STRING usValue,
2803{
2805
2806 /* if no value is specified, assume TRUE
2807 * if a value is specified, it must be a '1' */
2808 if (Option->EaValueLength == 0 || *usValue->Buffer == L'1')
2809 *Value = TRUE;
2810 else
2811 *Value = FALSE;
2812
2813 DbgP(" '%ls' -> '%wZ' -> %u\n",
2814 (LPWSTR)Option->EaName, usValue, *Value);
2815 return status;
2816}
2817
2820 IN PUNICODE_STRING usValue,
2822 IN DWORD Minimum,
2823 IN DWORD Maximum)
2824{
2826 LPWSTR Name = (LPWSTR)Option->EaName;
2827
2828 if (Option->EaValueLength) {
2829 status = RtlUnicodeStringToInteger(usValue, 0, Value);
2830 if (status == STATUS_SUCCESS) {
2831#ifdef IMPOSE_MINMAX_RWSIZES
2832 if (*Value < Minimum)
2833 *Value = Minimum;
2834 if (*Value > Maximum)
2835 *Value = Maximum;
2836 DbgP(" '%ls' -> '%wZ' -> %lu\n", Name, usValue, *Value);
2837#endif
2838 }
2839 else
2840 print_error("Failed to convert %s='%wZ' to unsigned long.\n",
2841 Name, usValue);
2842 }
2843
2844 return status;
2845}
2846
2851{
2854 LPWSTR Name;
2855 size_t NameLen;
2856 UNICODE_STRING usValue;
2857 Option = EaBuffer;
2858 while (status == STATUS_SUCCESS) {
2859 Name = (LPWSTR)Option->EaName;
2860 NameLen = Option->EaNameLength/sizeof(WCHAR);
2861
2862 usValue.Length = usValue.MaximumLength = Option->EaValueLength;
2863 usValue.Buffer = (PWCH)(Option->EaName +
2864 Option->EaNameLength + sizeof(WCHAR));
2865
2866 if (wcsncmp(L"ro", Name, NameLen) == 0) {
2867 status = nfs41_MountConfig_ParseBoolean(Option, &usValue,
2868 &Config->ReadOnly);
2869 }
2870 else if (wcsncmp(L"writethru", Name, NameLen) == 0) {
2871 status = nfs41_MountConfig_ParseBoolean(Option, &usValue,
2872 &Config->write_thru);
2873 }
2874 else if (wcsncmp(L"nocache", Name, NameLen) == 0) {
2875 status = nfs41_MountConfig_ParseBoolean(Option, &usValue,
2876 &Config->nocache);
2877 }
2878 else if (wcsncmp(L"timeout", Name, NameLen) == 0) {
2879 status = nfs41_MountConfig_ParseDword(Option, &usValue,
2880 &Config->timeout, UPCALL_TIMEOUT_DEFAULT,
2882 }
2883 else if (wcsncmp(L"rsize", Name, NameLen) == 0) {
2884 status = nfs41_MountConfig_ParseDword(Option, &usValue,
2885 &Config->ReadSize, MOUNT_CONFIG_RW_SIZE_MIN,
2887 }
2888 else if (wcsncmp(L"wsize", Name, NameLen) == 0) {
2889 status = nfs41_MountConfig_ParseDword(Option, &usValue,
2890 &Config->WriteSize, MOUNT_CONFIG_RW_SIZE_MIN,
2892 }
2893 else if (wcsncmp(L"srvname", Name, NameLen) == 0) {
2894 if (usValue.Length > Config->SrvName.MaximumLength)
2896 else
2897 RtlCopyUnicodeString(&Config->SrvName, &usValue);
2898 }
2899 else if (wcsncmp(L"mntpt", Name, NameLen) == 0) {
2900 if (usValue.Length > Config->MntPt.MaximumLength)
2902 else
2903 RtlCopyUnicodeString(&Config->MntPt, &usValue);
2904 }
2905 else if (wcsncmp(L"sec", Name, NameLen) == 0) {
2906 if (usValue.Length > Config->SecFlavor.MaximumLength)
2908 else
2909 RtlCopyUnicodeString(&Config->SecFlavor, &usValue);
2910 }
2911 else {
2913 print_error("Unrecognized option '%ls' -> '%wZ'\n",
2914 Name, usValue);
2915 }
2916
2917 if (Option->NextEntryOffset == 0)
2918 break;
2919
2920 Option = (PFILE_FULL_EA_INFORMATION)
2921 ((PBYTE)Option + Option->NextEntryOffset);
2922 }
2923
2924 return status;
2925}
2926
2928 IN PUNICODE_STRING SrvCallName,
2929 IN PUNICODE_STRING NetRootName)
2930{
2932
2933 if (NetRootName->Length == SrvCallName->Length + NfsPrefix.Length) {
2934 const UNICODE_STRING NetRootPrefix = {
2935 NfsPrefix.Length,
2936 NetRootName->MaximumLength - SrvCallName->Length,
2937 &NetRootName->Buffer[SrvCallName->Length/2]
2938 };
2939 if (RtlCompareUnicodeString(&NetRootPrefix, &NfsPrefix, FALSE) == 0)
2941 }
2942 return status;
2943}
2944
2946 IN PUNICODE_STRING sec_flavor_name,
2948{
2949 if (RtlCompareUnicodeString(sec_flavor_name, &AUTH_SYS_NAME, FALSE) == 0)
2951 else if (RtlCompareUnicodeString(sec_flavor_name, &AUTHGSS_KRB5_NAME, FALSE) == 0)
2953 else if (RtlCompareUnicodeString(sec_flavor_name, &AUTHGSS_KRB5I_NAME, FALSE) == 0)
2955 else if (RtlCompareUnicodeString(sec_flavor_name, &AUTHGSS_KRB5P_NAME, FALSE) == 0)
2957 else return STATUS_INVALID_PARAMETER;
2958 return STATUS_SUCCESS;
2959}
2960
2962 PLUID id)
2963{
2967 SECURITY_CLIENT_CONTEXT clnt_sec_ctx;
2968
2969 SeCaptureSubjectContext(&sec_ctx);
2972 sec_qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
2973 sec_qos.EffectiveOnly = 0;
2974 status = SeCreateClientSecurityFromSubjectContext(&sec_ctx, &sec_qos, 1,
2975 &clnt_sec_ctx);
2976 if (status) {
2977 print_error("nfs41_GetLUID: SeCreateClientSecurityFromSubjectContext "
2978 "failed %x\n", status);
2979 goto release_sec_ctx;
2980 }
2982 if (status) {
2983 print_error("SeQueryAuthenticationIdToken failed %x\n", status);
2984 goto release_clnt_sec_ctx;
2985 }
2986release_clnt_sec_ctx:
2987 SeDeleteClientSecurity(&clnt_sec_ctx);
2988release_sec_ctx:
2989 SeReleaseSubjectContext(&sec_ctx);
2990
2991 return status;
2992}
2993
2997{
3001
3004 sec_qos.ImpersonationLevel = level;
3005 sec_qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
3006 sec_qos.EffectiveOnly = 0;
3007 status = SeCreateClientSecurityFromSubjectContext(&ctx, &sec_qos, 1, out_ctx);
3008 if (status != STATUS_SUCCESS) {
3009 print_error("SeCreateClientSecurityFromSubjectContext "
3010 "failed with %x\n", status);
3011 }
3012#ifdef DEBUG_MOUNT
3013 DbgP("Created client security token %p\n", out_ctx->ClientToken);
3014#endif
3016
3017 return status;
3018}
3019
3020#ifdef __REACTOS__
3022#else
3024#endif
3025 IN OUT PMRX_CREATENETROOT_CONTEXT pCreateNetRootContext)
3026{
3030 pCreateNetRootContext->pVNetRoot;
3031 __notnull PMRX_NET_ROOT pNetRoot = pVNetRoot->pNetRoot;
3032 __notnull PMRX_SRV_CALL pSrvCall = pNetRoot->pSrvCall;
3033 __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
3034 NFS41GetVNetRootExtension(pVNetRoot);
3035 __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
3036 NFS41GetNetRootExtension(pNetRoot);
3037 NFS41GetDeviceExtension(pCreateNetRootContext->RxContext,DevExt);
3038 DWORD nfs41d_version = DevExt->nfs41d_version;
3039 nfs41_mount_entry *existing_mount = NULL;
3040 LUID luid;
3041 BOOLEAN found_existing_mount = FALSE, found_matching_flavor = FALSE;
3042
3043 ASSERT((NodeType(pNetRoot) == RDBSS_NTC_NETROOT) &&
3044 (NodeType(pNetRoot->pSrvCall) == RDBSS_NTC_SRVCALL));
3045
3046#ifdef DEBUG_MOUNT
3047 DbgEn();
3048 print_srv_call(0, pSrvCall);
3049 print_net_root(0, pNetRoot);
3050 print_v_net_root(0, pVNetRoot);
3051
3052 DbgP("pVNetRoot=%p pNetRoot=%p pSrvCall=%p\n", pVNetRoot, pNetRoot, pSrvCall);
3053 DbgP("pNetRoot=%wZ Type=%d pSrvCallName=%wZ VirtualNetRootStatus=0x%x "
3054 "NetRootStatus=0x%x\n", pNetRoot->pNetRootName,
3055 pNetRoot->Type, pSrvCall->pSrvCallName,
3056 pCreateNetRootContext->VirtualNetRootStatus,
3057 pCreateNetRootContext->NetRootStatus);
3058#endif
3059
3060 if (pNetRoot->Type != NET_ROOT_DISK && pNetRoot->Type != NET_ROOT_WILD) {
3061 print_error("nfs41_CreateVNetRoot: Unsupported NetRoot Type %u\n",
3062 pNetRoot->Type);
3064 goto out;
3065 }
3066
3067 pVNetRootContext->session = INVALID_HANDLE_VALUE;
3068
3069 /* In order to cooperate with other network providers, we must
3070 * only claim paths of the form '\\server\nfs4\path' */
3071 status = has_nfs_prefix(pSrvCall->pSrvCallName, pNetRoot->pNetRootName);
3072 if (status) {
3073 print_error("nfs41_CreateVNetRoot: NetRootName %wZ doesn't match "
3074 "'\\nfs4'!\n", pNetRoot->pNetRootName);
3075 goto out;
3076 }
3077 pNetRoot->MRxNetRootState = MRX_NET_ROOT_STATE_GOOD;
3078 pNetRoot->DeviceType = FILE_DEVICE_DISK;
3079
3082 if (Config == NULL) {
3084 goto out;
3085 }
3087
3088 if (pCreateNetRootContext->RxContext->Create.EaLength) {
3089 /* parse the extended attributes for mount options */
3091 pCreateNetRootContext->RxContext->Create.EaBuffer,
3092 pCreateNetRootContext->RxContext->Create.EaLength,
3093 Config);
3094 if (status != STATUS_SUCCESS)
3095 goto out_free;
3096 pVNetRootContext->read_only = Config->ReadOnly;
3097 pVNetRootContext->write_thru = Config->write_thru;
3098 pVNetRootContext->nocache = Config->nocache;
3099 } else {
3100 /* use the SRV_CALL name (without leading \‍) as the hostname */
3101 Config->SrvName.Buffer = pSrvCall->pSrvCallName->Buffer + 1;
3102 Config->SrvName.Length =
3103 pSrvCall->pSrvCallName->Length - sizeof(WCHAR);
3104 Config->SrvName.MaximumLength =
3105 pSrvCall->pSrvCallName->MaximumLength - sizeof(WCHAR);
3106 }
3107 pVNetRootContext->MountPathLen = Config->MntPt.Length;
3108 pVNetRootContext->timeout = Config->timeout;
3109
3110 status = map_sec_flavor(&Config->SecFlavor, &pVNetRootContext->sec_flavor);
3111 if (status != STATUS_SUCCESS) {
3112 DbgP("Invalid rpcsec security flavor %wZ\n", &Config->SecFlavor);
3113 goto out_free;
3114 }
3115
3116 status = nfs41_GetLUID(&luid);
3117 if (status)
3118 goto out_free;
3119
3120 if (!pNetRootContext->mounts_init) {
3121#ifdef DEBUG_MOUNT
3122 DbgP("Initializing mount array\n");
3123#endif
3124 ExInitializeFastMutex(&pNetRootContext->mountLock);
3125 InitializeListHead(&pNetRootContext->mounts.head);
3126 pNetRootContext->mounts_init = TRUE;
3127 } else {
3129
3130 ExAcquireFastMutex(&pNetRootContext->mountLock);
3131 pEntry = &pNetRootContext->mounts.head;
3132 pEntry = pEntry->Flink;
3133 while (pEntry != NULL) {
3134 existing_mount = (nfs41_mount_entry *)CONTAINING_RECORD(pEntry,
3136#ifdef DEBUG_MOUNT
3137 DbgP("comparing %x.%x with %x.%x\n", luid.HighPart, luid.LowPart,
3138 existing_mount->login_id.HighPart, existing_mount->login_id.LowPart);
3139#endif
3140 if (RtlEqualLuid(&luid, &existing_mount->login_id)) {
3141#ifdef DEBUG_MOUNT
3142 DbgP("Found a matching LUID entry\n");
3143#endif
3144 found_existing_mount = TRUE;
3145 switch(pVNetRootContext->sec_flavor) {
3146 case RPCSEC_AUTH_SYS:
3147 if (existing_mount->authsys_session != INVALID_HANDLE_VALUE)
3148 pVNetRootContext->session =
3149 existing_mount->authsys_session;
3150 break;
3152 if (existing_mount->gssi_session != INVALID_HANDLE_VALUE)
3153 pVNetRootContext->session = existing_mount->gss_session;
3154 break;
3156 if (existing_mount->gss_session != INVALID_HANDLE_VALUE)
3157 pVNetRootContext->session = existing_mount->gssi_session;
3158 break;
3160 if (existing_mount->gssp_session != INVALID_HANDLE_VALUE)
3161 pVNetRootContext->session = existing_mount->gssp_session;
3162 break;
3163 }
3164 if (pVNetRootContext->session &&
3165 pVNetRootContext->session != INVALID_HANDLE_VALUE)
3166 found_matching_flavor = 1;
3167 break;
3168 }
3169 if (pEntry->Flink == &pNetRootContext->mounts.head)
3170 break;
3171 pEntry = pEntry->Flink;
3172 }
3173 ExReleaseFastMutex(&pNetRootContext->mountLock);
3174#ifdef DEBUG_MOUNT
3175 if (!found_matching_flavor)
3176 DbgP("Didn't find matching security flavor\n");
3177#endif
3178 }
3179
3180 /* send the mount upcall */
3181 status = nfs41_mount(Config, pVNetRootContext->sec_flavor,
3182 &pVNetRootContext->session, &nfs41d_version,
3183 &pVNetRootContext->FsAttrs);
3184 if (status != STATUS_SUCCESS) {
3185 BOOLEAN MountsEmpty;
3186 nfs41_IsListEmpty(pNetRootContext->mountLock,
3187 pNetRootContext->mounts, MountsEmpty);
3188 if (!found_existing_mount && MountsEmpty)
3189 pNetRootContext->mounts_init = FALSE;
3190 pVNetRootContext->session = INVALID_HANDLE_VALUE;
3191 goto out_free;
3192 }
3193 pVNetRootContext->timeout = Config->timeout;
3194
3195 if (!found_existing_mount) {
3196 /* create a new mount entry and add it to the list */
3200 if (entry == NULL) {
3202 goto out_free;
3203 }
3204 entry->authsys_session = entry->gss_session =
3205 entry->gssi_session = entry->gssp_session = INVALID_HANDLE_VALUE;
3206 switch (pVNetRootContext->sec_flavor) {
3207 case RPCSEC_AUTH_SYS:
3208 entry->authsys_session = pVNetRootContext->session; break;
3210 entry->gss_session = pVNetRootContext->session; break;
3212 entry->gssi_session = pVNetRootContext->session; break;
3214 entry->gssp_session = pVNetRootContext->session; break;
3215 }
3216 RtlCopyLuid(&entry->login_id, &luid);
3217 nfs41_AddEntry(pNetRootContext->mountLock,
3218 pNetRootContext->mounts, entry);
3219 } else if (!found_matching_flavor) {
3220 ASSERT(existing_mount != NULL);
3221 /* modify existing mount entry */
3222#ifdef DEBUG_MOUNT
3223 DbgP("Using existing %d flavor session 0x%x\n",
3224 pVNetRootContext->sec_flavor);
3225#endif
3226 switch (pVNetRootContext->sec_flavor) {
3227 case RPCSEC_AUTH_SYS:
3228 existing_mount->authsys_session = pVNetRootContext->session; break;
3230 existing_mount->gss_session = pVNetRootContext->session; break;
3232 existing_mount->gssi_session = pVNetRootContext->session; break;
3234 existing_mount->gssp_session = pVNetRootContext->session; break;
3235 }
3236 }
3237 pNetRootContext->nfs41d_version = nfs41d_version;
3238#ifdef DEBUG_MOUNT
3239 DbgP("Saving new session 0x%x\n", pVNetRootContext->session);
3240#endif
3241#ifdef STORE_MOUNT_SEC_CONTEXT
3243 &pVNetRootContext->mount_sec_ctx);
3244#endif
3245
3246out_free:
3248out:
3249 pCreateNetRootContext->VirtualNetRootStatus = status;
3250 if (pNetRoot->Context == NULL)
3251 pCreateNetRootContext->NetRootStatus = status;
3252 pCreateNetRootContext->Callback(pCreateNetRootContext);
3253
3254 /* RDBSS expects that MRxCreateVNetRoot returns STATUS_PENDING
3255 * on success or failure */
3257#ifdef DEBUG_MOUNT
3258 DbgEx();
3259#endif
3260 return status;
3261}
3262
3263#ifdef __REACTOS__
3265#else
3267#endif
3268 IN PUNICODE_STRING FilePathName,
3269 IN PMRX_SRV_CALL SrvCall,
3270 OUT PUNICODE_STRING NetRootName,
3271 OUT PUNICODE_STRING RestOfName OPTIONAL)
3272{
3273 ULONG length = FilePathName->Length;
3274 PWCH w = FilePathName->Buffer;
3275 PWCH wlimit = (PWCH)(((PCHAR)w)+length);
3276 PWCH wlow;
3277
3278 w += (SrvCall->pSrvCallName->Length/sizeof(WCHAR));
3279 NetRootName->Buffer = wlow = w;
3280 /* parse the entire path into NetRootName */
3281#if USE_ENTIRE_PATH
3282 w = wlimit;
3283#else
3284 for (;;) {
3285 if (w >= wlimit)
3286 break;
3287 if ((*w == OBJ_NAME_PATH_SEPARATOR) && (w != wlow))
3288 break;
3289 w++;
3290 }
3291#endif
3292 NetRootName->Length = NetRootName->MaximumLength
3293 = (USHORT)((PCHAR)w - (PCHAR)wlow);
3294#ifdef DEBUG_MOUNT
3295 DbgP("In: pSrvCall %p PathName=%wZ SrvCallName=%wZ Out: NetRootName=%wZ\n",
3296 SrvCall, FilePathName, SrvCall->pSrvCallName, NetRootName);
3297#endif
3298 return;
3299
3300}
3301
3302#ifdef __REACTOS__
3304#else
3306#endif
3307 PMRX_SRV_CALL pSrvCall,
3308 BOOLEAN Force)
3309{
3311 PNFS41_SERVER_ENTRY pServerEntry = (PNFS41_SERVER_ENTRY)(pSrvCall->Context);
3312
3313#ifdef DEBUG_MOUNT
3314 DbgEn();
3315#endif
3316 print_srv_call(0, pSrvCall);
3317
3318 if (pSrvCall->Context == NULL)
3319 goto out;
3320
3321#ifndef __REACTOS__
3323 NULL, pSrvCall);
3324#else
3325 InterlockedCompareExchangePointer((void * volatile *)&pServerEntry->pRdbssSrvCall,
3326 NULL, pSrvCall);
3327#endif
3328 RxFreePool(pServerEntry);
3329
3330 pSrvCall->Context = NULL;
3331out:
3332#ifdef DEBUG_MOUNT
3333 DbgEx();
3334#endif
3335 return status;
3336}
3337
3338#ifdef __REACTOS__
3340#else
3342#endif
3343 IN OUT PMRX_NET_ROOT pNetRoot,
3345{
3347 PNFS41_NETROOT_EXTENSION pNetRootContext =
3350 nfs41_mount_entry *mount_tmp;
3351
3352#ifdef DEBUG_MOUNT
3353 DbgEn();
3354 print_net_root(1, pNetRoot);
3355#endif
3356
3357 if (pNetRoot->Type != NET_ROOT_DISK && pNetRoot->Type != NET_ROOT_WILD) {
3359 goto out;
3360 }
3361
3362 if (pNetRootContext == NULL || !pNetRootContext->mounts_init) {
3363 print_error("nfs41_FinalizeNetRoot: No valid session established\n");
3364 goto out;
3365 }
3366
3367 if (pNetRoot->NumberOfFcbs > 0 || pNetRoot->NumberOfSrvOpens > 0) {
3368 print_error("%d open Fcbs %d open SrvOpens\n", pNetRoot->NumberOfFcbs,
3369 pNetRoot->NumberOfSrvOpens);
3370 goto out;
3371 }
3372
3373 do {
3374 nfs41_GetFirstMountEntry(pNetRootContext->mountLock,
3375 pNetRootContext->mounts, mount_tmp);
3376 if (mount_tmp == NULL)
3377 break;
3378#ifdef DEBUG_MOUNT
3379 DbgP("Removing entry luid %x.%x from mount list\n",
3380 mount_tmp->login_id.HighPart, mount_tmp->login_id.LowPart);
3381#endif
3382 if (mount_tmp->authsys_session != INVALID_HANDLE_VALUE) {
3384 pNetRootContext->nfs41d_version, UPCALL_TIMEOUT_DEFAULT);
3385 if (status)
3386 print_error("nfs41_unmount AUTH_SYS failed with %d\n", status);
3387 }
3388 if (mount_tmp->gss_session != INVALID_HANDLE_VALUE) {
3389 status = nfs41_unmount(mount_tmp->gss_session,
3390 pNetRootContext->nfs41d_version, UPCALL_TIMEOUT_DEFAULT);
3391 if (status)
3392 print_error("nfs41_unmount RPCSEC_GSS_KRB5 failed with %d\n",
3393 status);
3394 }
3395 if (mount_tmp->gssi_session != INVALID_HANDLE_VALUE) {
3396 status = nfs41_unmount(mount_tmp->gssi_session,
3397 pNetRootContext->nfs41d_version, UPCALL_TIMEOUT_DEFAULT);
3398 if (status)
3399 print_error("nfs41_unmount RPCSEC_GSS_KRB5I failed with %d\n",
3400 status);
3401 }
3402 if (mount_tmp->gssp_session != INVALID_HANDLE_VALUE) {
3403 status = nfs41_unmount(mount_tmp->gssp_session,
3404 pNetRootContext->nfs41d_version, UPCALL_TIMEOUT_DEFAULT);
3405 if (status)
3406 print_error("nfs41_unmount RPCSEC_GSS_KRB5P failed with %d\n",
3407 status);
3408 }
3409 nfs41_RemoveEntry(pNetRootContext->mountLock, mount_tmp);
3410 RxFreePool(mount_tmp);
3411 } while (1);
3412 /* ignore any errors from unmount */
3414
3415 // check if there is anything waiting in the upcall or downcall queue
3416 do {
3418 if (tmp != NULL) {
3419 DbgP("Removing entry from upcall list\n");
3422 KeSetEvent(&tmp->cond, 0, FALSE);
3423 } else
3424 break;
3425 } while (1);
3426
3427 do {
3429 if (tmp != NULL) {
3430 DbgP("Removing entry from downcall list\n");
3433 KeSetEvent(&tmp->cond, 0, FALSE);
3434 } else
3435 break;
3436 } while (1);
3437out:
3438#ifdef DEBUG_MOUNT
3439 DbgEx();
3440#endif
3441 return status;
3442}
3443
3444#ifdef __REACTOS__
3446#else
3448#endif
3449 IN OUT PMRX_V_NET_ROOT pVNetRoot,
3451{
3453 PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
3454 NFS41GetVNetRootExtension(pVNetRoot);
3455#ifdef DEBUG_MOUNT
3456 DbgEn();
3457 print_v_net_root(1, pVNetRoot);
3458#endif
3459 if (pVNetRoot->pNetRoot->Type != NET_ROOT_DISK &&
3460 pVNetRoot->pNetRoot->Type != NET_ROOT_WILD)
3462#ifdef STORE_MOUNT_SEC_CONTEXT
3463 else if (pVNetRootContext->session != INVALID_HANDLE_VALUE) {
3464#ifdef DEBUG_MOUNT
3465 DbgP("nfs41_FinalizeVNetRoot: deleting security context: %p\n",
3466 pVNetRootContext->mount_sec_ctx.ClientToken);
3467#endif
3468 SeDeleteClientSecurity(&pVNetRootContext->mount_sec_ctx);
3469 }
3470#endif
3471#ifdef DEBUG_MOUNT
3472 DbgEx();
3473#endif
3474 return status;
3475}
3476
3479{
3481 return TRUE;
3482 return FALSE;
3483}
3484
3486 ULONG disposition)
3487{
3488 if (disposition == FILE_CREATE || disposition == FILE_OPEN_IF ||
3489 disposition == FILE_OVERWRITE_IF || disposition == FILE_SUPERSEDE)
3490 return TRUE;
3491 return FALSE;
3492}
3493
3496 PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext)
3497{
3498 PFILE_FS_ATTRIBUTE_INFORMATION attrs = &pVNetRootContext->FsAttrs;
3499 LONG len = attrs->MaximumComponentNameLength, count = 1, i;
3500 PWCH p = name->Buffer;
3501 for (i = 0; i < name->Length / 2; i++) {
3502 if (p[0] == L'\\') count = 1;
3503 else {
3504 if (p[0] == L'\0') return FALSE;
3505 if (count > len) return TRUE;
3506 count++;
3507 }
3508 p++;
3509 }
3510 return FALSE;
3511}
3512
3515{
3516 LONG i;
3517 PWCH p = name->Buffer;
3518 for (i = 0; i < name->Length / 2; i++) {
3519 if (p[0] == L':') return TRUE;
3520 else if (p[0] == L'\0') return FALSE;
3521 p++;
3522 }
3523 return FALSE;
3524}
3525
3527{
3528 /* from ms-fsa page 52 */
3529 if ((params->CreateOptions & FILE_DELETE_ON_CLOSE) &&
3530 !(params->DesiredAccess & DELETE))
3531 return FALSE;
3532 if ((params->CreateOptions & FILE_DIRECTORY_FILE) &&
3533 (params->Disposition == FILE_SUPERSEDE ||
3534 params->Disposition == FILE_OVERWRITE ||
3535 params->Disposition == FILE_OVERWRITE_IF))
3536 return FALSE;
3537 if ((params->CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING) &&
3538 (params->DesiredAccess & FILE_APPEND_DATA) &&
3539 !(params->DesiredAccess & FILE_WRITE_DATA))
3540 return FALSE;
3541 /* from ms-fsa 3.1.5.1.1 page 56 */
3542 if ((params->CreateOptions & FILE_DIRECTORY_FILE) &&
3543 (params->FileAttributes & FILE_ATTRIBUTE_TEMPORARY))
3544 return FALSE;
3545 return TRUE;
3546}
3547
3549 DWORD status,
3550 USHORT len)
3551{
3552 switch (status) {
3553 case NO_ERROR: return STATUS_SUCCESS;
3555 if (len > 0) return STATUS_ACCESS_DENIED;
3556 else return STATUS_SUCCESS;
3567 case ERROR_REPARSE: return STATUS_REPARSE;
3571 default:
3572 print_error("[ERROR] nfs41_Create: upcall returned %d returning "
3573 "STATUS_INSUFFICIENT_RESOURCES\n", status);
3575 }
3576}
3577
3579 DWORD disposition,
3580 DWORD errno)
3581{
3582 switch(disposition) {
3583 case FILE_SUPERSEDE:
3585 else return FILE_SUPERSEDED;
3586 case FILE_CREATE: return FILE_CREATED;
3587 case FILE_OPEN: return FILE_OPENED;
3588 case FILE_OPEN_IF:
3590 else return FILE_OPENED;
3591 case FILE_OVERWRITE: return FILE_OVERWRITTEN;
3592 case FILE_OVERWRITE_IF:
3594 else return FILE_OVERWRITTEN;
3595 default:
3596 print_error("unknown disposition %d\n", disposition);
3597 return FILE_OPENED;
3598 }
3599}
3600
3603 IN ULONG disposition)
3604{
3605 /* don't pass cygwin EAs */
3606 if (AnsiStrEq(&NfsV3Attributes, ea->EaName, ea->EaNameLength)
3607 || AnsiStrEq(&NfsActOnLink, ea->EaName, ea->EaNameLength)
3608 || AnsiStrEq(&NfsSymlinkTargetName, ea->EaName, ea->EaNameLength))
3609 return FALSE;
3610 /* only set EAs on file creation */
3611 return disposition == FILE_SUPERSEDE || disposition == FILE_CREATE
3612 || disposition == FILE_OPEN_IF || disposition == FILE_OVERWRITE
3613 || disposition == FILE_OVERWRITE_IF;
3614}
3615
3617 IN PRX_CONTEXT RxContext)
3618{
3620 PNT_CREATE_PARAMETERS params = &RxContext->Create.NtCreateParameters;
3621 __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
3622 __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
3623 NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
3625 &pVNetRootContext->FsAttrs;
3626 __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
3627 NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
3628 __notnull PMRX_FCB Fcb = RxContext->pFcb;
3629 __notnull PNFS41_FCB nfs41_fcb = (PNFS41_FCB)Fcb->Context;
3631 RxContext->CurrentIrp->AssociatedIrp.SystemBuffer;
3632
3633 if (Fcb->pNetRoot->Type != NET_ROOT_DISK &&
3634 Fcb->pNetRoot->Type != NET_ROOT_WILD) {
3635 print_error("nfs41_Create: Unsupported NetRoot Type %u\n",
3636 Fcb->pNetRoot->Type);
3638 goto out;
3639 }
3640
3642 print_error("FCB_STATE_PAGING_FILE not implemented\n");
3644 goto out;
3645 }
3646
3647 if (!pNetRootContext->mounts_init) {
3648 print_error("nfs41_Create: No valid session established\n");
3650 goto out;
3651 }
3652
3653 if (isStream(SrvOpen->pAlreadyPrefixedName)) {
3655 goto out;
3656 }
3657
3658 if (pVNetRootContext->read_only &&
3659 (params->DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA))) {
3661 goto out;
3662 }
3663
3664 /* if FCB was marked for deletion and opened multiple times, as soon
3665 * as first close happen, FCB transitions into delete_pending state
3666 * no more opens allowed
3667 */
3668 if (Fcb->OpenCount && nfs41_fcb->DeletePending) {
3670 goto out;
3671 }
3672
3673 /* ms-fsa: 3.1.5.1.2.1 page 68 */
3674 if (Fcb->OpenCount && nfs41_fcb->StandardInfo.DeletePending &&
3675 !(params->ShareAccess & FILE_SHARE_DELETE) &&
3676 (params->DesiredAccess & (FILE_EXECUTE | FILE_READ_DATA |
3679 goto out;
3680 }
3681
3682 /* rdbss seems miss this sharing_violation check */
3683 if (Fcb->OpenCount && params->Disposition == FILE_SUPERSEDE) {
3684#ifdef __REACTOS__
3685 if ((!RxContext->CurrentIrpSp->FileObject->SharedRead &&
3686 (params->DesiredAccess & FILE_READ_DATA)) ||
3687 ((!RxContext->CurrentIrpSp->FileObject->SharedWrite &&
3688 (params->DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA |
3690 (!RxContext->CurrentIrpSp->FileObject->SharedDelete &&
3691 (params->DesiredAccess & DELETE)))) {
3692#else
3693 if ((!RxContext->CurrentIrpSp->FileObject->SharedRead &&
3694 (params->DesiredAccess & FILE_READ_DATA)) ||
3695 (!RxContext->CurrentIrpSp->FileObject->SharedWrite &&
3696 (params->DesiredAccess & (FILE_WRITE_DATA | FILE_APPEND_DATA |
3698 (!RxContext->CurrentIrpSp->FileObject->SharedDelete &&
3699 (params->DesiredAccess & DELETE)))) {
3700#endif
3702 goto out;
3703 }
3704 }
3705 if (isFilenameTooLong(SrvOpen->pAlreadyPrefixedName, pVNetRootContext)) {
3707 goto out;
3708 }
3709
3710 if (!areOpenParamsValid(params)) {
3712 goto out;
3713 }
3714
3715 /* from ms-fsa 3.1.5.1.1 page 56 */
3716 if ((params->CreateOptions & FILE_DELETE_ON_CLOSE) &&
3717 (params->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
3719 goto out;
3720 }
3721
3722 if (ea) {
3723 /* ignore cygwin EAs when checking support and access */
3724 if (!AnsiStrEq(&NfsV3Attributes, ea->EaName, ea->EaNameLength) &&
3725 !AnsiStrEq(&NfsActOnLink, ea->EaName, ea->EaNameLength) &&
3726 !AnsiStrEq(&NfsSymlinkTargetName, ea->EaName, ea->EaNameLength)) {
3727 if (!(FsAttrs->FileSystemAttributes & FILE_SUPPORTS_EXTENDED_ATTRIBUTES)) {
3729 goto out;
3730 }
3731 }
3732 } else if (RxContext->CurrentIrpSp->Parameters.Create.EaLength) {
3734 goto out;
3735 }
3736
3737out:
3738 return status;
3739}
3740
3741#ifdef __REACTOS__
3743#else
3745#endif
3746 IN OUT PRX_CONTEXT RxContext)
3747{
3750 PNT_CREATE_PARAMETERS params = &RxContext->Create.NtCreateParameters;
3752 RxContext->CurrentIrp->AssociatedIrp.SystemBuffer;
3753 __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
3754 __notnull PNFS41_V_NET_ROOT_EXTENSION pVNetRootContext =
3755 NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
3756 __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
3757 NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
3758 __notnull PMRX_FCB Fcb = RxContext->pFcb;
3759 __notnull PNFS41_FCB nfs41_fcb = (PNFS41_FCB)Fcb->Context;
3760 PNFS41_FOBX nfs41_fobx = NULL;
3761 BOOLEAN oldDeletePending = nfs41_fcb->StandardInfo.DeletePending;
3762#ifdef ENABLE_TIMINGS
3763 LARGE_INTEGER t1, t2;
3765#endif
3766
3767 ASSERT( NodeType(SrvOpen) == RDBSS_NTC_SRVOPEN );
3768
3769#ifdef DEBUG_OPEN
3770 DbgEn();
3771 print_debug_header(RxContext);
3772 print_nt_create_params(1, RxContext->Create.NtCreateParameters);
3773 if (ea) print_ea_info(0, ea);
3774#endif
3775
3776 status = check_nfs41_create_args(RxContext);
3777 if (status) goto out;
3778
3779#if defined(STORE_MOUNT_SEC_CONTEXT) && defined (USE_MOUNT_SEC_CONTEXT)
3780 status = nfs41_UpcallCreate(NFS41_OPEN, &pVNetRootContext->mount_sec_ctx,
3781#else
3783#endif
3784 pVNetRootContext->session, INVALID_HANDLE_VALUE,
3785 pNetRootContext->nfs41d_version,
3786 SrvOpen->pAlreadyPrefixedName, &entry);
3787 if (status) goto out;
3788
3789 entry->u.Open.access_mask = params->DesiredAccess;
3790 entry->u.Open.access_mode = params->ShareAccess;
3791 entry->u.Open.attrs = params->FileAttributes;
3792 if (!(params->CreateOptions & FILE_DIRECTORY_FILE))
3793 entry->u.Open.attrs |= FILE_ATTRIBUTE_ARCHIVE;
3794 entry->u.Open.disp = params->Disposition;
3795 entry->u.Open.copts = params->CreateOptions;
3796 entry->u.Open.srv_open = SrvOpen;
3797 /* treat the NfsActOnLink ea as FILE_OPEN_REPARSE_POINT */
3798 if ((ea && AnsiStrEq(&NfsActOnLink, ea->EaName, ea->EaNameLength)) ||
3799 (entry->u.Open.access_mask & DELETE))
3800 entry->u.Open.copts |= FILE_OPEN_REPARSE_POINT;
3801 if (isDataAccess(params->DesiredAccess) || isOpen2Create(params->Disposition))
3802 entry->u.Open.open_owner_id = InterlockedIncrement(&open_owner_id);
3803 // if we are creating a file check if nfsv3attributes were passed in
3804 if (params->Disposition != FILE_OPEN && params->Disposition != FILE_OVERWRITE) {
3805 entry->u.Open.mode = 0777;
3806 if (ea && AnsiStrEq(&NfsV3Attributes, ea->EaName, ea->EaNameLength)) {
3807 nfs3_attrs *attrs = (nfs3_attrs *)(ea->EaName + ea->EaNameLength + 1);
3808#ifdef DEBUG_OPEN
3809 DbgP("creating file with mode %o\n", attrs->mode);
3810#endif
3811 entry->u.Open.mode = attrs->mode;
3812 }
3813 if (params->FileAttributes & FILE_ATTRIBUTE_READONLY)
3814 entry->u.Open.mode = 0444;
3815 }
3816 if (entr