Using XmlUriResolver to provide credentials to remote share

264 views Asked by At

Thank you in advance for any and all help.

I have seen several post on Stack Overflow and other sites on the net (including Microsoft Docs), but none seeming to help resolve my issue.

I am working on a project that connects to a xml file on a remote file share from WinPE. I have used suggestions from another post on SO about using the XmlUriResolver class to "moderate" success.

The issue I am currently being faced with is either a "Access Denied" error (several attempts to modify the XmlUriResolver.Credentials class) or a complete failure without any reason for failure. I am assuming it is going to be another "Access Denied" error, but my try/catch (Exception e) isn't capturing the reason.

Below is a snippet and relevant part of the method I am trying to implement:

relativeSysData = relativeSysData.Replace(@"\", "/");
SysdataXml = $"file://{_globaldata.Server}/{_globaldata.Share}/{relativeSysData}";

XmlUrlResolver XmlResolver = new XmlUrlResolver();
XmlResolver.Credentials = new NetworkCredential(_UserName, 
                                                _Password);

XmlReaderSettings xmlSettings = new XmlReaderSettings();
xmlSettings.XmlResolver = XmlResolver;
LogWriter.WriteLogFile((int)LogWriter.EventID.Xml, (int)LogWriter.EventType.Info,
                      $"Connecting to (remote) System information store at: {SysdataXml}");

xDoc = XDocument.Load(XmlReader.Create(SysdataXml, xmlSettings));
if (xDoc == null)
{
    LogWriter.WriteLogFile((int)LogWriter.EventID.XmlError, (int)LogWriter.EventType.Error,
                          $"Unable to connect to the (remote) data store located at: {SysdataXml}");
    deploy = false;
    capture = false;
    return result;
}

This part of the method is specific to accessing the remote data. I have a try/catch statement encompassing all of the method.

If I have an open connection to the Network Share, the method will work flawlessly, but will cause the application this application starts to fail - due to an open connection already.

I have a possible alternative to work round this solution but will cost extra lines of code.

Any help in resolving this matter, without resorting to WNetAddConnection() will be gratefully received

Kind Regards

Richie

N.B. I am aware that this is an authentication issue.

1

There are 1 answers

0
R.McInnes-Piper On BEST ANSWER

After research into how the XmlUrlResolver class works, I think that it may be referencing/accessing API's that are not included within the WinPE API framework.

After testing, I have used the WNetAddConnection2() API to connect to the Server and authenticate before anything happens, ensuring that the local name of the NETRESOURCE structure is left null, and that DisplayType is set to Server.

public static int ConnectToServer()
    {
        int result = 0;

        var _netresource = new NetResource()
        {
            scope = _ResourceScope.GlobalNetwork,
            ResourceType = _ResourceType.Any,
            DisplayType = _ResourceDisplayType.Server,
            RemoteName = $@"\\{Program._globaldata.Server}"
        };

        string _username = $@"{Program._globaldata.Server}\RemoteDKBuild";
        string _passsword = "Hic3nuasno6epyndtenars4yDifrts";

        var _connectiontype = (int)_ConnectionType.Interactive | (int)_ConnectionType.Temporary;

        LogWriter.WriteLogFile((int)LogWriter.EventID.NetMan, (int)LogWriter.EventType.Info,
                                $@"Attempting to connect to: \\{_netresource.RemoteName}");
        result = WNetAddConnection2(_netresource, _passsword, _username, _connectiontype);
        var res = Marshal.GetLastWin32Error();
        if (result !=0)
        {
            LogWriter.WriteLogFile((int)LogWriter.EventID.NetMan, (int)LogWriter.EventType.Error,
                                    $@"Failed to connect to: \\{_netresource.RemoteName}, Return Result: {result.ToString()}, Win32 Error Code: {res.ToString()}");
            result = res;
        }
        else
        {
            LogWriter.WriteLogFile((int)LogWriter.EventID.NetMan, (int)LogWriter.EventType.Info,
                                    $@"Connection to: \\{_netresource.RemoteName} has been successfull.");
        }

        return result;
    }

[DllImport("mpr.dll", SetLastError = true)]
private static extern int WNetAddConnection2(NetResource netResource, string password, string username, int flags);