IopReplaceSymlinkPath

NTSTATUS __stdcall IopReplaceSymlinkPath(
        WCHAR *OutputBuffer,
        UINT64 Position,
        _FILE_OBJECT *FileObject,
        _REPARSE_DATA_BUFFER *ReparseBuffer,
        UINT64 PathStart,
        UINT16 CurrentLength,
        UINT64 MaxLength){
  unsigned int v7; 
  USHORT SubstituteNameLength; 
  unsigned __int64 Reserved; 
  WCHAR *v12; 
  WCHAR *v13; 
  unsigned int v14; 
  WCHAR *v15; 
  wchar_t *v16; 
  WCHAR *v17; 
  UINT16 v18; 
  _WORD *v19; 
  __int64 v20; 
  NTSTATUS result; 
  wchar_t *v22; 
  unsigned __int16 Length; 
  unsigned __int16 v24; 
  wchar_t v25; 
  __int16 v26; 
  wchar_t *Buffer; 
  WCHAR v28; 
  wchar_t v29; 
  __int64 v30; 
  USHORT v31; 
  wchar_t v32; 
  struct _REPARSE_DATA_BUFFER::$EDE85F431271D6DB35F60DFE09C35EC8::$E4726FB01B43180CB4D608E8FC40A3CF *Src; 

  v7 = PathStart;
  SubstituteNameLength = ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength;
  Reserved = ReparseBuffer->Reserved;
  v12 = &OutputBuffer[(unsigned int)PathStart];
  v31 = SubstituteNameLength;
  v13 = &OutputBuffer[(unsigned int)Position];
  LOWORD(PathStart) = 0;
  LOWORD(v14) = 0;
  if( (unsigned int)Position < v7 )
    return -1073741192;
  Src = &ReparseBuffer->GenericReparseBuffer + ReparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameOffset + 12;
  if( *(_WORD *)Src->DataBuffer == 92 )
  {
    if( wcsnicmp(OutputBuffer, L"\\Device\\Mup", 0xBu) )
      goto LABEL_8;
    Length = FileObject->FileName.Length;
    v24 = 0;
    v32 = *FileObject->FileName.Buffer;
    v25 = v32;
    v26 = (v32 != 59) + 3;
    if( (Length & 0xFFFE) != 0 )
    {
      do
      {
        Buffer = FileObject->FileName.Buffer;
        v28 = Buffer[v24];
        if( v28 == 92 )
        {
          --v26;
          if( v25 != 59 && v26 == 2 )
          {
            if( (unsigned __int16)(v24 + 1) < (unsigned __int16)(Length >> 1) && Buffer[v24 + 1] != 59 )
              v26 = 0;
            v25 = v32;
          }
          if( !v26 )
            goto LABEL_36;
        }
        *v13 = v28;
        ++v24;
        Length = FileObject->FileName.Length;
        ++v13;
      }
      while( v24 < (unsigned __int16)(Length >> 1) );
    }
    if( !v26 )
    {
LABEL_36:
      if( v24 < (unsigned __int16)(Length >> 1) )
      {
        v29 = FileObject->FileName.Buffer[v24];
        do
        {
          *v13 = v29;
          ++v24;
          ++v13;
          v29 = FileObject->FileName.Buffer[v24];
        }
        while( v29 != 92 && v24 < (unsigned __int16)(FileObject->FileName.Length >> 1) );
      }
      SubstituteNameLength = v31;
      v30 = v7 + v24;
      v18 = 2 * v24 + CurrentLength;
      v12 = &OutputBuffer[v30];
      goto LABEL_9;
    }
    return -1073741192;
  }
  v15 = &OutputBuffer[(unsigned int)Position];
  v16 = FileObject->FileName.Buffer;
  LOWORD(PathStart) = FileObject->FileName.Length - Reserved;
  v14 = (unsigned __int16)PathStart;
  memmove(v15, v16, (unsigned __int16)PathStart);
  v17 = &v13[(unsigned __int64)v14 >> 1];
  if( v17 != v12 )
  {
    do
    {
      if( *v17 == 92 )
        break;
      LOWORD(v14) = v14 - 2;
      *v17-- = 0;
      LOWORD(PathStart) = v14;
    }
    while( v17 != v12 );
    if( v17 < v12 )
      return -1073741192;
  }
  v13 = v17 + 1;
LABEL_8:
  v18 = CurrentLength;
LABEL_9:
  if( SubstituteNameLength )
  {
    memmove(v13, Src, SubstituteNameLength);
    LOWORD(v14) = v31 + v14;
    LOWORD(PathStart) = v14;
    v13 += (unsigned __int64)SubstituteNameLength >> 1;
  }
  if( (_WORD)Reserved )
  {
    v19 = (wchar_t *)((char *)FileObject->FileName.Buffer + FileObject->FileName.Length - Reserved);
    if( *(v13 - 1) == 92 && *v19 == 92 )
    {
      *v13-- = 0;
      LOWORD(v14) = v14 - 2;
    }
    memmove(v13, v19, Reserved);
    LOWORD(PathStart) = Reserved + v14;
    v13 += Reserved >> 1;
  }
  *v13 = 0;
  v20 = -1i64;
  do
    ++v20;
  while( v12[v20] );
  result = FsRtlRemoveDotsFromPath(v12, 2 * v20, (UINT16 *)&PathStart);
  if( result >= 0 )
  {
    v22 = FileObject->FileName.Buffer;
    FileObject->FileName.Length = v18 + PathStart;
    FileObject->FileName.MaximumLength = MaxLength;
    if( OutputBuffer != v22 )
    {
      if( v22 )
        ExFreePoolWithTag(v22, 0);
      FileObject->FileName.Buffer = OutputBuffer;
    }
    return 0;
  }
  return result;
}

Referenced by:

IopSymlinkApplyToOpenedName