pastebin - collaborative debugging tool
nrubsig.kpaste.net RSS


mount reparse prototype, 2025-02-05
Posted by Anonymous on Wed 5th Feb 2025 09:06
raw | new post

  1. diff --git a/daemon/readdir.c b/daemon/readdir.c
  2. index 14325bf..5b40e18 100644
  3. --- a/daemon/readdir.c
  4. +++ b/daemon/readdir.c
  5. @@ -25,6 +25,7 @@
  6.  #include <stdlib.h>
  7.  #include <stdbool.h>
  8.  #include <string.h>
  9. +#include "nfs41_build_features.h"
  10.  #include "nfs41_driver.h" /* for |FILE_INFO_TIME_NOT_SET| */
  11.  #include "from_kernel.h"
  12.  #include "nfs41_ops.h"
  13. @@ -403,8 +404,23 @@ static void readdir_copy_full_dir_info(
  14.       * the 'dir' command to show files as <SYMLINK>, and triggers a
  15.       * FSCTL_GET_REPARSE_POINT to query the symlink target
  16.       */
  17. +#ifdef NFS41_DRIVER_EXPERIMENTAL_JUNCTION_ABSOLUTESYMLINK_SUPPORT
  18. +    if (entry->attr_info.type == NF4LNK) {
  19. +        /* BUG: |entry->name| is wrong, we have to get the VALUE of the symlink instead */
  20. +        if (!strncmp(entry->name, "/cygdrive/")) {
  21. +            info->fifdi.EaSize = IO_REPARSE_TAG_MOUNT_POINT;
  22. +        }
  23. +        else {
  24. +            info->fifdi.EaSize = IO_REPARSE_TAG_SYMLINK;
  25. +        }
  26. +    }
  27. +    else {
  28. +        info->fifdi.EaSize = 0;
  29. +    }
  30. +#else
  31.      info->fifdi.EaSize = entry->attr_info.type == NF4LNK ?
  32.          IO_REPARSE_TAG_SYMLINK : 0;
  33. +#endif /* NFS41_DRIVER_EXPERIMENTAL_JUNCTION_ABSOLUTESYMLINK_SUPPORT */
  34.  }
  35.  
  36.  static void readdir_copy_both_dir_info(
  37. diff --git a/nfs41_build_features.h b/nfs41_build_features.h
  38. index a127e40..af7d643 100644
  39. --- a/nfs41_build_features.h
  40. +++ b/nfs41_build_features.h
  41. @@ -181,4 +181,12 @@
  42.   */
  43.  #define NFS41_DRIVER_DEFAULT_NFS4MINORVERSION 2
  44.  
  45. +/*
  46. + * NFS41_DRIVER_EXPERIMENTAL_JUNCTION_ABSOLUTESYMLINK_SUPPORT - use
  47. + * Win32 Junctions to represent absolute symlinks
  48. + * Example:
  49. + * $ powershell -Command 'New-Item -Path junc_builds -ItemType Junction -Value L:\builds'
  50. + */
  51. +#define NFS41_DRIVER_EXPERIMENTAL_JUNCTION_ABSOLUTESYMLINK_SUPPORT 1
  52. +
  53.  #endif /* !_NFS41_DRIVER_BUILDFEATURES_ */
  54. diff --git a/sys/nfs41sys_driver.h b/sys/nfs41sys_driver.h
  55. index f14beb5..7a3500a 100644
  56. --- a/sys/nfs41sys_driver.h
  57. +++ b/sys/nfs41sys_driver.h
  58. @@ -776,6 +776,10 @@ void unmarshal_nfs41_symlink(
  59.      unsigned char **buf);
  60.  NTSTATUS nfs41_SetSymlinkReparsePoint(
  61.      IN OUT PRX_CONTEXT RxContext);
  62. +#ifdef NFS41_DRIVER_EXPERIMENTAL_JUNCTION_ABSOLUTESYMLINK_SUPPORT
  63. +NTSTATUS nfs41_SetJunctionReparsePoint(
  64. +    IN OUT PRX_CONTEXT RxContext);
  65. +#endif /* NFS41_DRIVER_EXPERIMENTAL_JUNCTION_ABSOLUTESYMLINK_SUPPORT */
  66.  NTSTATUS nfs41_GetSymlinkReparsePoint(
  67.      IN OUT PRX_CONTEXT RxContext);
  68.  
  69. diff --git a/sys/nfs41sys_reparse.c b/sys/nfs41sys_reparse.c
  70. index 0b1e726..5e62a33 100644
  71. --- a/sys/nfs41sys_reparse.c
  72. +++ b/sys/nfs41sys_reparse.c
  73. @@ -89,6 +89,11 @@ NTSTATUS nfs41_SetReparsePoint(
  74.          case IO_REPARSE_TAG_SYMLINK:
  75.              status = nfs41_SetSymlinkReparsePoint(RxContext);
  76.              break;
  77. +#ifdef NFS41_DRIVER_EXPERIMENTAL_JUNCTION_ABSOLUTESYMLINK_SUPPORT
  78. +        case IO_REPARSE_TAG_MOUNT_POINT:
  79. +            status = nfs41_SetJunctionReparsePoint(RxContext);
  80. +            break;
  81. +#endif /* NFS41_DRIVER_EXPERIMENTAL_JUNCTION_ABSOLUTESYMLINK_SUPPORT */
  82.          default:
  83.              status = STATUS_NOT_IMPLEMENTED;
  84.              DbgP("nfs41_SetReparsePoint: "
  85. diff --git a/sys/nfs41sys_symlink.c b/sys/nfs41sys_symlink.c
  86. index 6e04074..ef2abab 100644
  87. --- a/sys/nfs41sys_symlink.c
  88. +++ b/sys/nfs41sys_symlink.c
  89. @@ -135,6 +135,8 @@ NTSTATUS map_symlink_errors(
  90.  {
  91.      switch (status) {
  92.      case NO_ERROR:                  return STATUS_SUCCESS;
  93. +    case ERROR_FILE_NOT_FOUND:      return STATUS_OBJECT_NAME_NOT_FOUND;
  94. +    case ERROR_PATH_NOT_FOUND:      return STATUS_OBJECT_PATH_NOT_FOUND;
  95.      case ERROR_INVALID_REPARSE_DATA: return STATUS_IO_REPARSE_DATA_INVALID;
  96.      case ERROR_NOT_A_REPARSE_POINT: return STATUS_NOT_A_REPARSE_POINT;
  97.      case ERROR_ACCESS_DENIED:       return STATUS_ACCESS_DENIED;
  98. @@ -161,19 +163,20 @@ static void print_reparse_buffer(
  99.      PREPARSE_DATA_BUFFER Reparse)
  100.  {
  101.      UNICODE_STRING name;
  102. -    DbgP("ReparseTag:           %08X\n", Reparse->ReparseTag);
  103. +    DbgP("ReparseTag:           0x%lx\n", (long)Reparse->ReparseTag);
  104.      DbgP("ReparseDataLength:    %8u\n", Reparse->ReparseDataLength);
  105.      DbgP("Reserved:             %8u\n", Reparse->Reserved);
  106. -    DbgP("SubstituteNameOffset: %8u\n",
  107. +    if (Reparse->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
  108. +        DbgP("SubstituteNameOffset: %u\n",
  109.              Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset);
  110. -    DbgP("SubstituteNameLength: %8u\n",
  111. +        DbgP("SubstituteNameLength: %u\n",
  112.              Reparse->SymbolicLinkReparseBuffer.SubstituteNameLength);
  113. -    DbgP("PrintNameOffset:      %8u\n",
  114. +        DbgP("PrintNameOffset: %u\n",
  115.              Reparse->SymbolicLinkReparseBuffer.PrintNameOffset);
  116. -    DbgP("PrintNameLength:      %8u\n",
  117. +        DbgP("PrintNameLength: %u\n",
  118.              Reparse->SymbolicLinkReparseBuffer.PrintNameLength);
  119. -    DbgP("Flags:                %08X\n",
  120. -         Reparse->SymbolicLinkReparseBuffer.Flags);
  121. +        DbgP("Flags: 0x%lx\n",
  122. +            (long)Reparse->SymbolicLinkReparseBuffer.Flags);
  123.  
  124.          name.Buffer = &Reparse->SymbolicLinkReparseBuffer.PathBuffer[
  125.              Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)];
  126. @@ -187,6 +190,29 @@ static void print_reparse_buffer(
  127.              Reparse->SymbolicLinkReparseBuffer.PrintNameLength;
  128.              DbgP("PrintName: '%wZ'\n", &name);
  129.      }
  130. +    else if (Reparse->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
  131. +        DbgP("SubstituteNameOffset: %u\n",
  132. +            Reparse->MountPointReparseBuffer.SubstituteNameOffset);
  133. +        DbgP("SubstituteNameLength: %u\n",
  134. +            Reparse->MountPointReparseBuffer.SubstituteNameLength);
  135. +        DbgP("PrintNameOffset: %u\n",
  136. +            Reparse->MountPointReparseBuffer.PrintNameOffset);
  137. +        DbgP("PrintNameLength: %u\n",
  138. +            Reparse->MountPointReparseBuffer.PrintNameLength);
  139. +
  140. +        name.Buffer = &Reparse->MountPointReparseBuffer.PathBuffer[
  141. +            Reparse->MountPointReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)];
  142. +        name.MaximumLength = name.Length =
  143. +            Reparse->MountPointReparseBuffer.SubstituteNameLength;
  144. +        DbgP("SubstituteName: '%wZ'\n", &name);
  145. +
  146. +        name.Buffer = &Reparse->MountPointReparseBuffer.PathBuffer[
  147. +            Reparse->MountPointReparseBuffer.PrintNameOffset/sizeof(WCHAR)];
  148. +        name.MaximumLength = name.Length =
  149. +            Reparse->MountPointReparseBuffer.PrintNameLength;
  150. +            DbgP("PrintName: '%wZ'\n", &name);
  151. +    }
  152. +}
  153.  
  154.  static
  155.  NTSTATUS check_nfs41_setsymlinkreparse_args(
  156. @@ -247,12 +273,6 @@ NTSTATUS check_nfs41_setsymlinkreparse_args(
  157.              "IsReparseTagValid() failed\n");
  158.          goto out;
  159.      }
  160. -    if (Reparse->ReparseTag != IO_REPARSE_TAG_SYMLINK) {
  161. -        status = STATUS_IO_REPARSE_TAG_MISMATCH;
  162. -        DbgP("check_nfs41_setsymlinkreparse_args: "
  163. -            "Reparse->ReparseTag != IO_REPARSE_TAG_SYMLINK\n");
  164. -        goto out;
  165. -    }
  166.  out:
  167.      return status;
  168.  }
  169. @@ -291,6 +311,13 @@ NTSTATUS nfs41_SetSymlinkReparsePoint(
  170.          goto out;
  171.      }
  172.  
  173. +    if (Reparse->ReparseTag != IO_REPARSE_TAG_SYMLINK) {
  174. +        status = STATUS_IO_REPARSE_TAG_MISMATCH;
  175. +        DbgP("nfs41_SetSymlinkReparsePoint: "
  176. +            "Reparse->ReparseTag != IO_REPARSE_TAG_SYMLINK\n");
  177. +        goto out;
  178. +    }
  179. +
  180.      TargetName.MaximumLength = TargetName.Length =
  181.          Reparse->SymbolicLinkReparseBuffer.PrintNameLength;
  182.      TargetName.Buffer = &Reparse->SymbolicLinkReparseBuffer.PathBuffer[
  183. @@ -316,6 +343,131 @@ out:
  184.      return status;
  185.  }
  186.  
  187. +#ifdef NFS41_DRIVER_EXPERIMENTAL_JUNCTION_ABSOLUTESYMLINK_SUPPORT
  188. +NTSTATUS nfs41_SetJunctionReparsePoint(
  189. +    IN OUT PRX_CONTEXT RxContext)
  190. +{
  191. +    NTSTATUS status;
  192. +    UNICODE_STRING TargetName;
  193. +    __notnull XXCTL_LOWIO_COMPONENT *FsCtl = &RxContext->LowIoContext.ParamsFor.FsCtl;
  194. +    __notnull PREPARSE_DATA_BUFFER Reparse = (PREPARSE_DATA_BUFFER)FsCtl->pInputBuffer;
  195. +    __notnull PNFS41_FOBX Fobx = NFS41GetFobxExtension(RxContext->pFobx);
  196. +    __notnull PMRX_SRV_OPEN SrvOpen = RxContext->pRelevantSrvOpen;
  197. +    __notnull PNFS41_V_NET_ROOT_EXTENSION VNetRootContext =
  198. +        NFS41GetVNetRootExtension(SrvOpen->pVNetRoot);
  199. +    __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  200. +        NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
  201. +    nfs41_updowncall_entry *entry;
  202. +    PWSTR prefixed_targetname = NULL;
  203. +
  204. +#ifdef DEBUG_SYMLINK
  205. +    DbgEn();
  206. +    print_debug_header(RxContext);
  207. +    print_reparse_buffer(Reparse);
  208. +#endif
  209. +
  210. +    DbgP("nfs41_SetJunctionReparsePoint: ReparseTag: '%s'/0x%04lx\n",
  211. +        reparsetag2string(Reparse->ReparseTag),
  212. +        (long)Reparse->ReparseTag);
  213. +
  214. +    status = check_nfs41_setsymlinkreparse_args(RxContext);
  215. +    if (status) {
  216. +        DbgP("nfs41_SetJunctionReparsePoint: "
  217. +            "check_nfs41_setsymlinkreparse_args() failed, "
  218. +            "status=0xlx\n",
  219. +                (long)status);
  220. +        goto out;
  221. +    }
  222. +
  223. +    if (Reparse->ReparseTag != IO_REPARSE_TAG_MOUNT_POINT) {
  224. +        status = STATUS_IO_REPARSE_TAG_MISMATCH;
  225. +        DbgP("nfs41_SetJunctionReparsePoint: "
  226. +            "Reparse->ReparseTag != IO_REPARSE_TAG_MOUNT_POINT\n");
  227. +        goto out;
  228. +    }
  229. +
  230. +    TargetName.MaximumLength = TargetName.Length =
  231. +        Reparse->MountPointReparseBuffer.SubstituteNameLength;
  232. +    TargetName.Buffer = &Reparse->MountPointReparseBuffer.PathBuffer[
  233. +        Reparse->MountPointReparseBuffer.SubstituteNameOffset/sizeof(WCHAR)];
  234. +
  235. +    if (!memcmp(&TargetName.Buffer[0], L"\\??\\",
  236. +        (4*sizeof(wchar_t)))) {
  237. +        TargetName.Buffer += 4;
  238. +        TargetName.MaximumLength = TargetName.Length =
  239. +            TargetName.Length-(4*sizeof(wchar_t));
  240. +    }
  241. +
  242. +    DbgP("nfs41_SetJunctionReparsePoint: TargetName='%wZ'\n",
  243. +        &TargetName);
  244. +
  245. +    wchar_t devletter;
  246. +    if ((TargetName.Buffer[1] != L':') || TargetName.Buffer[2] != L'\\') {
  247. +        status = STATUS_INVALID_PARAMETER;
  248. +        DbgP("nfs41_SetJunctionReparsePoint: "
  249. +            "non-drive letter path '%wZ' not supported\n", &TargetName);
  250. +        goto out;
  251. +    }
  252. +
  253. +    /* Skip "L:\" "*/
  254. +    devletter = towlower(TargetName.Buffer[0]);
  255. +    TargetName.Buffer += 3;
  256. +    TargetName.MaximumLength = TargetName.Length =
  257. +        TargetName.Length-(3*sizeof(wchar_t));
  258. +
  259. +    DbgP("nfs41_SetJunctionReparsePoint: dosletter='%C' path='%wZ'\n",
  260. +        devletter,
  261. +        &TargetName);
  262. +
  263. +    size_t prefixed_targetname_len = 4096*sizeof(wchar_t);
  264. +
  265. +    prefixed_targetname = RxAllocatePoolWithTag(NonPagedPoolNx,
  266. +        prefixed_targetname_len, NFS41_MM_POOLTAG);
  267. +    if (prefixed_targetname == NULL) {
  268. +        status = STATUS_INSUFFICIENT_RESOURCES;
  269. +        goto out;
  270. +    }
  271. +
  272. +    /*
  273. +     * Stuff Cygwin /cygdrive/<dosletter>/ prefix in front of path,
  274. +     * userland daemon will convert the backslashes to slashes
  275. +     */
  276. +    (void)_snwprintf(prefixed_targetname,
  277. +        prefixed_targetname_len, L"\\cygdrive\\%C\\%wZ",
  278. +        devletter,
  279. +        &TargetName);
  280. +
  281. +    /* Put new buffer into target name */
  282. +    TargetName.MaximumLength = TargetName.Length =
  283. +        (USHORT)(wcslen(prefixed_targetname)*sizeof(wchar_t));
  284. +    TargetName.Buffer = prefixed_targetname;
  285. +
  286. +    DbgP("nfs41_SetJunctionReparsePoint: new TargetName='%wZ'\n",
  287. +        &TargetName);
  288. +
  289. +    status = nfs41_UpcallCreate(NFS41_SYSOP_SYMLINK, &Fobx->sec_ctx,
  290. +        VNetRootContext->session, Fobx->nfs41_open_state,
  291. +        pNetRootContext->nfs41d_version, SrvOpen->pAlreadyPrefixedName, &entry);
  292. +    if (status) goto out;
  293. +
  294. +    entry->u.Symlink.target = &TargetName;
  295. +    entry->u.Symlink.set = TRUE;
  296. +
  297. +    status = nfs41_UpcallWaitForReply(entry, VNetRootContext->timeout);
  298. +    if (status) goto out;
  299. +
  300. +    status = map_symlink_errors(entry->status);
  301. +    nfs41_UpcallDestroy(entry);
  302. +out:
  303. +    RxFreePool(prefixed_targetname);
  304. +
  305. +#ifdef DEBUG_SYMLINK
  306. +    DbgEx();
  307. +#endif
  308. +    return status;
  309. +}
  310. +#endif /* NFS41_DRIVER_EXPERIMENTAL_JUNCTION_ABSOLUTESYMLINK_SUPPORT */
  311. +
  312.  static
  313.  NTSTATUS check_nfs41_getsymlinkreparse_args(
  314.      PRX_CONTEXT RxContext)
  315. @@ -376,8 +528,7 @@ NTSTATUS nfs41_GetSymlinkReparsePoint(
  316.      __notnull PNFS41_NETROOT_EXTENSION pNetRootContext =
  317.          NFS41GetNetRootExtension(SrvOpen->pVNetRoot->pNetRoot);
  318.      nfs41_updowncall_entry *entry;
  319. -    const USHORT HeaderLen = FIELD_OFFSET(REPARSE_DATA_BUFFER,
  320. -        SymbolicLinkReparseBuffer.PathBuffer);
  321. +    PWSTR targetname_buffer = NULL;
  322.  
  323.  #ifdef DEBUG_SYMLINK
  324.      DbgEn();
  325. @@ -391,9 +542,16 @@ NTSTATUS nfs41_GetSymlinkReparsePoint(
  326.          goto out;
  327.      }
  328.  
  329. -    TargetName.Buffer = (PWCH)((PBYTE)FsCtl->pOutputBuffer + HeaderLen);
  330. -    TargetName.MaximumLength = (USHORT)min(FsCtl->OutputBufferLength -
  331. -        HeaderLen, 0xFFFF);
  332. +    size_t targetname_buffer_len = 4096*sizeof(wchar_t);
  333. +    targetname_buffer = RxAllocatePoolWithTag(NonPagedPoolNx,
  334. +        targetname_buffer_len, NFS41_MM_POOLTAG);
  335. +    if (targetname_buffer == NULL) {
  336. +        status = STATUS_INSUFFICIENT_RESOURCES;
  337. +        goto out;
  338. +    }
  339. +
  340. +    TargetName.Buffer = targetname_buffer;
  341. +    TargetName.MaximumLength = (USHORT)targetname_buffer_len;
  342.  
  343.      status = nfs41_UpcallCreate(NFS41_SYSOP_SYMLINK, &Fobx->sec_ctx,
  344.          VNetRootContext->session, Fobx->nfs41_open_state,
  345. @@ -411,27 +569,115 @@ NTSTATUS nfs41_GetSymlinkReparsePoint(
  346.          /* fill in the output buffer */
  347.          PREPARSE_DATA_BUFFER Reparse = (PREPARSE_DATA_BUFFER)
  348.              FsCtl->pOutputBuffer;
  349. +
  350. +        DbgP("nfs41_GetSymlinkReparsePoint: TargetName='%wZ'\n",
  351. +            &TargetName);
  352. +
  353. +        /* "/cygdrive/l/" == 12 characters */
  354. +        if ((TargetName.Length >= (12*sizeof(wchar_t))) &&
  355. +            (!memcmp(&TargetName.Buffer[0], L"/cygdrive/",
  356. +                (10*sizeof(wchar_t))))) {
  357. +            const USHORT HeaderLen = FIELD_OFFSET(REPARSE_DATA_BUFFER,
  358. +                MountPointReparseBuffer.PathBuffer);
  359. +
  360. +            DbgP("nfs41_GetSymlinkReparsePoint: Junction codepath\n");
  361. +
  362. +            wchar_t dosletter;
  363. +            dosletter = towupper(TargetName.Buffer[10]);
  364. +            TargetName.Buffer += 9;
  365. +            TargetName.MaximumLength = TargetName.Length =
  366. +                TargetName.Length-(9*sizeof(wchar_t));
  367. +            TargetName.Buffer[0] = dosletter;
  368. +            TargetName.Buffer[1] = L':';
  369. +            TargetName.Buffer[2] = L'/';
  370. +
  371. +            /* POSIX slash to Win32 backslash */
  372. +            size_t i;
  373. +            for (i=0 ; i < TargetName.Length ; i++) {
  374. +                if (TargetName.Buffer[i] == L'/')
  375. +                    TargetName.Buffer[i] = L'\\';
  376. +            }
  377. +
  378. +            DbgP("nfs41_GetSymlinkReparsePoint: new TargetName='%wZ'\n",
  379. +                &TargetName);
  380. +
  381. +            /* Copy data into FsCtl buffer  */
  382. +            (void)memcpy(((PBYTE)FsCtl->pOutputBuffer + HeaderLen),
  383. +                TargetName.Buffer, TargetName.Length);
  384. +            TargetName.Buffer =
  385. +                (PWCH)((PBYTE)FsCtl->pOutputBuffer + HeaderLen);
  386. +
  387. +            DbgP("nfs41_GetSymlinkReparsePoint: new TargetName='%wZ'\n",
  388. +                &TargetName);
  389. +
  390. +            Reparse->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
  391. +            Reparse->ReparseDataLength = HeaderLen + TargetName.Length -
  392. +                REPARSE_DATA_BUFFER_HEADER_SIZE;
  393. +            Reparse->Reserved = 0;
  394. +            /* PrintName and SubstituteName point to the same string */
  395. +            Reparse->MountPointReparseBuffer.SubstituteNameOffset = 0;
  396. +            Reparse->MountPointReparseBuffer.SubstituteNameLength =
  397. +                TargetName.Length;
  398. +            Reparse->MountPointReparseBuffer.PrintNameOffset = 0;
  399. +            Reparse->MountPointReparseBuffer.PrintNameLength =
  400. +                TargetName.Length;
  401. +
  402. +            print_reparse_buffer(Reparse);
  403. +
  404. +            RxContext->IoStatusBlock.Information =
  405. +                (ULONG_PTR)HeaderLen + TargetName.Length;
  406. +        }
  407. +        else {
  408. +            const USHORT HeaderLen = FIELD_OFFSET(REPARSE_DATA_BUFFER,
  409. +                SymbolicLinkReparseBuffer.PathBuffer);
  410. +
  411. +            DbgP("nfs41_GetSymlinkReparsePoint: Symlink codepath\n");
  412. +
  413. +            /* Copy data into FsCtl buffer  */
  414. +            (void)memcpy(((PBYTE)FsCtl->pOutputBuffer + HeaderLen),
  415. +                TargetName.Buffer, TargetName.Length);
  416. +            TargetName.Buffer =
  417. +                (PWCH)((PBYTE)FsCtl->pOutputBuffer + HeaderLen);
  418. +
  419.              Reparse->ReparseTag = IO_REPARSE_TAG_SYMLINK;
  420.              Reparse->ReparseDataLength = HeaderLen + TargetName.Length -
  421.                  REPARSE_DATA_BUFFER_HEADER_SIZE;
  422.              Reparse->Reserved = 0;
  423. -        Reparse->SymbolicLinkReparseBuffer.Flags = SYMLINK_FLAG_RELATIVE;
  424. +            Reparse->SymbolicLinkReparseBuffer.Flags =
  425. +                SYMLINK_FLAG_RELATIVE;
  426.              /* PrintName and SubstituteName point to the same string */
  427.              Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
  428.              Reparse->SymbolicLinkReparseBuffer.SubstituteNameLength =
  429.                  TargetName.Length;
  430.              Reparse->SymbolicLinkReparseBuffer.PrintNameOffset = 0;
  431. -        Reparse->SymbolicLinkReparseBuffer.PrintNameLength = TargetName.Length;
  432. +            Reparse->SymbolicLinkReparseBuffer.PrintNameLength =
  433. +                TargetName.Length;
  434. +
  435.              print_reparse_buffer(Reparse);
  436.  
  437.              RxContext->IoStatusBlock.Information =
  438.                  (ULONG_PTR)HeaderLen + TargetName.Length;
  439. +        }
  440.      } else if (status == STATUS_BUFFER_TOO_SMALL) {
  441. +        const size_t sym_hdr_len =
  442. +            FIELD_OFFSET(REPARSE_DATA_BUFFER,
  443. +                MountPointReparseBuffer.PathBuffer);
  444. +        const size_t mnt_hdr_len =
  445. +            FIELD_OFFSET(REPARSE_DATA_BUFFER,
  446. +                SymbolicLinkReparseBuffer.PathBuffer);
  447. +        /*
  448. +         * We don't know whether we have to return
  449. +         * |IO_REPARSE_TAG_MOUNT_POINT| or |IO_REPARSE_TAG_SYMLINK|,
  450. +         * so we return a size which can fit both
  451. +         */
  452. +#define MAX(a, b) (((a) > (b)) ? (a) : (b))
  453.          RxContext->InformationToReturn =
  454. -            (ULONG_PTR)HeaderLen + TargetName.Length;
  455. +            MAX(sym_hdr_len, mnt_hdr_len) + TargetName.Length;
  456.      }
  457.      nfs41_UpcallDestroy(entry);
  458.  out:
  459. +    RxFreePool(targetname_buffer);
  460. +
  461.  #ifdef DEBUG_SYMLINK
  462.      DbgEx();
  463.  #endif

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at