microsoft / ProjFS-Managed-API

A managed-code API for the Windows Projected File System
Other
145 stars 34 forks source link

Is there a way to retrieve the ProviderId and ContentId from a placeholder? #55

Closed FeralSquid closed 3 years ago

FeralSquid commented 3 years ago

Hello,

It would be helpful when debugging if I were able to get at this information ... is there a way to do so?

Also, similarly, it would be really nice if UpdateFileIfNeeded() could return a result that indicates if the file was actually updated (because providerId and/or contentId are different) or not. It currently appears to return "Ok" in both cases.

Thanks!

FeralSquid commented 3 years ago

ok, I believe I found them in the reparse point data buffer (providerId = offset 32, contentId = offset 160 as they are 128 bytes max each and don't appear to be variably sized).

Is the reparse data structure public / available somewhere (so I can use that instead of my hacks)? There is a decent bit of other info in there that I am not sure about yet.

Thanks!

FeralSquid commented 3 years ago

poking some more, I have:

[0-3] reparse tag id [4-7] reparse tag data length [8-11] ?? (always 2, perhaps a version number for the tag data format?) [12-15] flags?

it would be nice if you could at least confirm the version number part so I can detect when that changes and do this again ;)

thanks!

cgallred commented 3 years ago

There isn't a way to retrieve the ProviderId and ContentId. I can see how it would be useful.

The overall structure of the reparse point is publicly documented as REPARSE_DATA_BUFFER:

typedef struct _REPARSE_DATA_BUFFER {
  ULONG  ReparseTag;
  USHORT ReparseDataLength;
  USHORT Reserved;
  union {
    struct {
      USHORT SubstituteNameOffset;
      USHORT SubstituteNameLength;
      USHORT PrintNameOffset;
      USHORT PrintNameLength;
      ULONG  Flags;
      WCHAR  PathBuffer[1];
    } SymbolicLinkReparseBuffer;
    struct {
      USHORT SubstituteNameOffset;
      USHORT SubstituteNameLength;
      USHORT PrintNameOffset;
      USHORT PrintNameLength;
      WCHAR  PathBuffer[1];
    } MountPointReparseBuffer;
    struct {
      UCHAR DataBuffer[1];
    } GenericReparseBuffer;
  } DUMMYUNIONNAME;
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;

The undocumented ProjFS-specific payload lives in the GenericReparseBuffer.DataBuffer member at offset 0x8. You're correct about the offsets of ProviderId and ContentId. :-)