title: Access denied when using Net.Tcp Port Sharing Service
body: <p>This question is related to <a href="https://stackoverflow.com/questions/21708133/starting-processes-under-specific-credentials-from-a-windows-service">Starting processes under specific credentials from a Windows service</a>, but it's a different problem.</p>
  
  <p>I've started a process from a Windows service in the System session (0) under specific credentials, but it is unable to listen to a port sharing URL. It's using a "Worker" domain account on a Windows Server 2008 machine.</p>
  
  <p>My <strong>SMSvcHost.exe.config</strong> file: <a href="http://pastie.org/private/jxed8bdft0eir5uc371pq" rel="nofollow noreferrer">http://pastie.org/private/jxed8bdft0eir5uc371pq</a></p>
  
  <p>I've restarted the services and the machine as well, but it's still giving me this exception:</p>
  
  <pre><code>System.ServiceModel.CommunicationException: The service endpoint failed to listen on the URI 'net.tcp://localhost:5400/Agent/384' because access was denied.  Verify that the current user is granted access in the appropriate allowAccounts section of SMSvcHost.exe.config. ---&gt; System.ComponentModel.Win32Exception: Access is denied
     at System.ServiceModel.Activation.SharedMemory.Read(String name, String&amp; content)
     at System.ServiceModel.Channels.SharedConnectionListener.SharedListenerProxy.ReadEndpoint(String sharedMemoryName, String&amp; listenerEndpoint)
  </code></pre>
  
  <p>My <strong>ProcessHelper</strong> code that starts the process: <a href="http://pastie.org/private/iytqehsdfujrgil1decda" rel="nofollow noreferrer">http://pastie.org/private/iytqehsdfujrgil1decda</a>. I'm calling the <code>StartAsUserFromService</code> method.</p>
  
  <p>I suppose the link between the SID in the config and the account the process is running under is somehow not being made. But why?</p>
  
  <p>EDIT:</p>
  
  <p>I've double-checked that the config I'm editing is used by the service. I've tried adding the System account and Everyone explicitly, but it's still giving me an access denied error. It's like it's not looking at that config at all.</p>
  
  <p>How can I find where the missing permission is?</p>
  
  <p>EDIT:</p>
  
  <p>I reinstalled .NET 4.5.1 on the machine and all the Windows updates, still no luck.</p>
  
  <p>EDIT:</p>
  
  <p>Is this the correct way of duplicating a user token to allow it to use port sharing? Specifically the <code>SecurityDescriptor</code> bit?</p>
  
  <pre><code>private static ImpersonationResult ImpersonateUser(string domain, string username, string password)
  {
      IntPtr token = IntPtr.Zero;
      IntPtr primaryToken = IntPtr.Zero;
  
      try
      {
          // Get token
          bool bImpersonated = LogonUser(
              username,
              domain,
              password,
              (int)LogonType.NetworkClearText,
              (int)LogonProvider.Default,
              ref token);
  
          if (!bImpersonated)
          {
              throw new Exception(string.Format("Failed to impersonate identity. Error code: {0}", Marshal.GetLastWin32Error()));
          }
  
          SecurityDescriptor sd = new SecurityDescriptor();
          IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(sd));
          Marshal.StructureToPtr(sd, ptr, false);
          InitializeSecurityDescriptor(ptr, 1);
          sd = (SecurityDescriptor)Marshal.PtrToStructure(ptr, typeof(SecurityDescriptor));
  
          // Set up security
          bool bDecriptorSet = SetSecurityDescriptorDacl(
              ref sd,
              true,
              IntPtr.Zero,
              false);
  
          if (!bDecriptorSet)
          {
              throw new Exception(string.Format("Failed to set security descriptor. Error code: {0}", Marshal.GetLastWin32Error()));
          }
  
          SecurityAttributes processAttributes = new SecurityAttributes();
          processAttributes.lpSecurityDescriptor = ptr;
          processAttributes.nLength = (uint)Marshal.SizeOf(sd);
          processAttributes.bInheritHandle = true;
  
          // Duplicate token
          bool bTokenDuplicated = DuplicateTokenEx(
              token,
              0,
              ref processAttributes,
              (int)SecurityImpersonationLevel.SecurityImpersonation,
              (int)TokenType.TokenPrimary,
              ref primaryToken);
  
          if (!bTokenDuplicated)
          {
              throw new Exception(string.Format("Failed to duplicate identity token. Error code: {0}", Marshal.GetLastWin32Error()));
          }
  
          SecurityAttributes threadAttributes = new SecurityAttributes();
          threadAttributes.lpSecurityDescriptor = IntPtr.Zero;
          threadAttributes.nLength = 0;
          threadAttributes.bInheritHandle = false;
  
          // Got the token
          return new ImpersonationResult()
              {
                  Token = primaryToken,
                  ProcessAttributes = processAttributes,
                  ThreadAttributes = threadAttributes
              };
      }
      finally
      {
          FreeToken(token);
      }
  }
  
  private static void FreeToken(IntPtr token)
  {
      if (token != IntPtr.Zero)
      {
          CloseHandle(token);
      }
  }
  </code></pre>
  
  <p>EDIT:</p>
  
  <p>Here's the app.config bit of my process that enables port sharing: <a href="http://pastie.org/private/8ekqeps4d7rmo7hnktsw" rel="nofollow noreferrer">http://pastie.org/private/8ekqeps4d7rmo7hnktsw</a></p>
  
  <p>Here's an app.config bit of the service that starts the process: <a href="http://pastie.org/private/nqqcwz8bvjb5fzp48yavbw" rel="nofollow noreferrer">http://pastie.org/private/nqqcwz8bvjb5fzp48yavbw</a>. It has no problems using Port Sharing because it's running under the System account.</p>
  
  <p>The Port Sharing service itself is enabled, and I already mentioned that I've restarted the machine several times.</p>
  
  <p>The "Application Server" role is not installed, but when I go to add it, the TCP Port Sharing Role is already ticked and greyed out, so something else must have installed it. Does it come with .NET 4.5.1?</p>