Beispiel #1
0
        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType == typeof(System.String) &&
                value is RAPICallNode)
            {
                RAPICallNode call = value as RAPICallNode;

                return(String.Format("{0}({1}) => {2}", call.Name,
                                     call.Request.Summary, call.Response.Summary));
            }

            return(base.ConvertTo(context, culture, value, destinationType));
        }
Beispiel #2
0
        private void HandleRapiSession()
        {
            List<PacketSlice> slices = new List<PacketSlice>();
            TransactionNode node, req, resp;
            string str;
            UInt32 val, retVal, lastError;

            while (stream.GetBytesAvailable() > 0)
            {
                UInt32 msgLen, msgType;
                List<PacketSlice> msgLenSlices = new List<PacketSlice>(1);
                List<PacketSlice> msgTypeSlices = new List<PacketSlice>(1);

                // Message length
                msgLen = stream.ReadU32LE(msgLenSlices);

                if (msgLen == 5)
                {
                    node = new TransactionNode("RAPINotification");
                    node.Description = node.Name;

                    node.AddField("MessageType", "RAPI_NOTIFICATION", "Message type.", msgLenSlices);

                    val = stream.ReadU32LE(slices);
                    node.AddField("NotificationType", (val == 4) ? "REQUEST_NEW_CONNECTION" : StaticUtils.FormatFlags(val), "Notification type.", slices);

                    val = stream.ReadU32LE(slices);
                    node.AddField("Argument", val, "Argument.", slices);

                    session.AddNode(node);

                    if (stream.GetBytesAvailable() < 4)
                        break;
                    else
                        continue;
                }
                else if (msgLen == 1)
                {
                    node = new TransactionNode("RAPIKeepalive");
                    node.Description = node.Name;

                    req = new TransactionNode(node, "Request");
                    req.AddField("MessageType", "RAPI_PING", "Message type.", msgLenSlices);

                    stream = session.GetNextStreamDirection();
                    if (stream.GetBytesAvailable() < 4)
                        break;

                    stream.ReadU32LE(slices);

                    resp = new TransactionNode(node, "Response");
                    resp.AddField("MessageType", "RAPI_PONG", "Message type.", slices);

                    session.AddNode(node);

                    stream = session.GetNextStreamDirection();

                    if (stream.GetBytesAvailable() < 4)
                        break;
                    else
                        continue;
                }

                // Message type
                msgType = stream.ReadU32LE(msgTypeSlices);
                if (msgType >= rapiCallNames.Length)
                {
                    logger.AddMessage("Unknown call name: {0:x8}", msgType);
                    return;
                }

                string name = rapiCallNames[msgType];

                RAPICallNode call = new RAPICallNode(name);
                call.Description = call.Name;

                req = call.Request;
                resp = call.Response;

                req.AddField("MessageLength", msgLen, "Length of the RAPI request.", msgLenSlices);
                req.AddField("MessageType", String.Format("{0} (0x{1:x2})", name, msgType), "Type of the RAPI request.", msgTypeSlices);

                if (name == "CeRegOpenKeyEx")
                {
                    val = stream.ReadU32LE(slices);
                    req.AddField("hKey", StaticUtils.FormatRegKey(val),
                        "Handle to a currently open key or one of the following predefined reserved handle values:\n" +
                        "HKEY_CLASSES_ROOT\nHKEY_CURRENT_USER\nHKEY_LOCAL_MACHINE\nHKEY_USERS",
                        slices);

                    str = stream.ReadRAPIString(slices);
                    req.AddField("szSubKey", str,
                        "A null-terminated string containing the name of the subkey to open.",
                        slices);

                    req.Summary = String.Format("{0}, \"{1}\"", StaticUtils.FormatRegKey(val, true), str);

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError);

                    val = stream.ReadU32LE(slices);
                    string result = String.Format("0x{0:x8}", val);
                    resp.AddField("hkResult", result, "Handle to the opened key.", slices);

                    if (retVal == Constants.ERROR_SUCCESS)
                        resp.Summary = String.Format("{0}, {1}", StaticUtils.FormatRetVal(retVal, true), result);
                    else
                        resp.Summary = StaticUtils.FormatRetVal(retVal, true);
                }
                else if (name == "CeRegCreateKeyEx")
                {
                    val = stream.ReadU32LE(slices);
                    req.AddField("hKey", StaticUtils.FormatRegKey(val),
                        "Handle to a currently open key or one of the following predefined reserved handle values:\n" +
                        "HKEY_CLASSES_ROOT\nHKEY_CURRENT_USER\nHKEY_LOCAL_MACHINE\nHKEY_USERS", slices);

                    string szSubKey = stream.ReadRAPIString(slices);
                    req.AddField("szSubKey", (szSubKey != null) ? szSubKey : "(null)",
                        "A null-terminated string specifying the name of a subkey that this function opens or creates. " +
                        "The subkey specified must be a subkey of the key identified by the hKey parameter. This subkey " +
                        "must not begin with the backslash character (\\). If the parameter is NULL, then RegCreateKeyEx " +
                        "behaves like RegOpenKey, where it opens the key specified by hKey.", slices);

                    string szClass = stream.ReadRAPIString(slices);
                    req.AddField("szClass", (szClass != null) ? szClass : "(null)",
                        "A null-terminated string that specifies the class (object type) of this key. This parameter is " +
                        "ignored if the key already exists.", slices);

                    req.Summary = String.Format("{0}, {1}, {2}",
                        StaticUtils.FormatRegKey(val, true),
                        StaticUtils.FormatStringArgument(szSubKey),
                        StaticUtils.FormatStringArgument(szClass));

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError);

                    string result = String.Format("0x{0:x8}", stream.ReadU32LE(slices));
                    resp.AddField("hkResult", result, "Handle to the opened key.", slices);

                    UInt32 disposition = stream.ReadU32LE(slices);
                    resp.AddField("dwDisposition", StaticUtils.FormatRegDisposition(disposition),
                        "Receives one of REG_CREATED_NEW_KEY and REG_OPENED_EXISTING_KEY.",
                        slices);

                    if (retVal == Constants.ERROR_SUCCESS)
                        resp.Summary = String.Format("{0}, {1}, {2}",
                            StaticUtils.FormatRetVal(retVal, true), result, StaticUtils.FormatRegDisposition(disposition, true));
                    else
                        resp.Summary = StaticUtils.FormatRetVal(retVal, true);

                }
                else if (name == "CeRegCloseKey")
                {
                    val = stream.ReadU32LE(slices);
                    req.AddField("hKey", StaticUtils.FormatRegKey(val),
                        "Handle to the open key to close.", slices);

                    req.Summary = StaticUtils.FormatRegKey(val, true);

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError);

                    resp.Summary = StaticUtils.FormatRetVal(retVal, true);
                }
                else if (name == "CeRegQueryValueEx")
                {
                    val = stream.ReadU32LE(slices);
                    req.AddField("hKey", StaticUtils.FormatRegKey(val),
                        "Handle to a currently open key or any of the following predefined reserved handle values:\n" +
                        "HKEY_CLASSES_ROOT\nHKEY_CURRENT_USER\nHKEY_LOCAL_MACHINE\nHKEY_USERS", slices);

                    string szValueName = stream.ReadRAPIString(slices);
                    req.AddField("szValueName", szValueName,
                        "A string containing the name of the value to query.", slices);

                    UInt32 cbData = stream.ReadU32LE(slices);
                    req.AddField("cbData", cbData,
                        "A variable that specifies the maximum number of bytes to return.", slices);

                    req.Summary = String.Format("{0}, {1}, {2}",
                        StaticUtils.FormatRegKey(val, true),
                        StaticUtils.FormatStringArgument(szValueName),
                        cbData);

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError);

                    UInt32 dwType = stream.ReadU32LE(slices);
                    resp.AddField("dwType", StaticUtils.FormatRegType(dwType),
                        "The type of data associated with the specified value.",
                        slices);

                    cbData = stream.ReadU32LE(slices);
                    resp.AddField("cbData", Convert.ToString(cbData),
                        "The size of the data returned.", slices);

                    str = ReadAndFormatDataForRegType(dwType, cbData, slices);
                    if (str == null)
                        str = "NULL";
                    resp.AddField("Data", str, "The data returned.", slices);

                    resp.Summary = StaticUtils.FormatRetVal(retVal, true);
                }
                else if (name == "CeRegSetValueEx")
                {
                    UInt32 key = stream.ReadU32LE(slices);
                    req.AddField("hKey", StaticUtils.FormatRegKey(key),
                        "Handle to a currently open key or any of the following predefined reserved handle values:\n" +
                        "HKEY_CLASSES_ROOT\nHKEY_CURRENT_USER\nHKEY_LOCAL_MACHINE\nHKEY_USERS", slices);

                    string szValueName = stream.ReadRAPIString(slices);
                    req.AddField("szValueName", szValueName,
                        "String containing the name of the value to set. If a value with this name is not already " +
                        "present in the key, the function adds it to the key. If this parameter is NULL or an empty " +
                        "string, the function sets the type and data for the key's unnamed value. Registry keys do " +
                        "not have default values, but they can have one unnamed value, which can be of any type.",
                        slices);

                    UInt32 dwType = stream.ReadU32LE(slices);
                    req.AddField("dwType", StaticUtils.FormatRegType(dwType),
                        "Type of information to be stored as the value's data.",
                        slices);

                    UInt32 cbData = stream.ReadU32LE(slices);
                    req.AddField("cbData", Convert.ToString(cbData),
                        "Specifies the size, in bytes, of the information passed in the the Data field.",
                        slices);

                    str = ReadAndFormatDataForRegType(dwType, cbData, slices);
                    if (str == null)
                        str = "NULL";
                    req.AddField("Data", str, "Buffer containing the data to be stored with the specified value name.",
                                 slices);

                    string dataSummary;
                    if (dwType == Constants.REG_DWORD || dwType == Constants.REG_DWORD_BIG_ENDIAN)
                    {
                        dataSummary = str;
                    }
                    else
                        dataSummary = String.Format("[{0} bytes]", cbData);

                    req.Summary = String.Format("{0}, {1}, {2}, {3}",
                        StaticUtils.FormatRegKey(key), StaticUtils.FormatStringArgument(szValueName), StaticUtils.FormatRegType(dwType), dataSummary);

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError);

                    resp.Summary = StaticUtils.FormatRetVal(retVal, true);

                }
                else if (name == "CeProcessConfig")
                {
                    str = stream.ReadRAPIString(slices);
                    req.AddXMLField("szRequest", str, "Config request.", slices);

                    UInt32 flags = stream.ReadU32LE(slices);
                    req.AddField("dwFlags", StaticUtils.FormatFlags(flags), "Flags.", slices);

                    req.Summary = String.Format("[{0} bytes], 0x{1:x8}",
                        str.Length, flags);

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError);

                    str = stream.ReadRAPIString(slices);
                    resp.AddXMLField("szResponse", str, "Config response.", slices);

                    if (retVal == Constants.ERROR_SUCCESS)
                        resp.Summary = String.Format("{0}, [{1} bytes]",
                            StaticUtils.FormatRetVal(retVal, true), (str != null) ? str.Length : 0);
                    else
                        resp.Summary = StaticUtils.FormatRetVal(retVal, true);

                }
                else if (name == "CeGetDesktopDeviceCaps")
                {
                    string caps = FormatDeviceCaps(stream.ReadU32LE(slices));
                    req.AddField("nIndex", caps, "The item to return.", slices);

                    req.Summary = caps;

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError, false);

                    resp.Summary = StaticUtils.FormatValue(retVal);
                }
                else if (name == "CeSyncStart")
                {
                    string xml = stream.ReadRAPIString(slices);
                    req.AddXMLField("szXML", (xml != null) ? xml : "(null)",
                                    "Optional message.", slices);

                    if (xml != null)
                        req.Summary = String.Format("[{0} bytes]", xml.Length);
                    else
                        req.Summary = "NULL";

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError);

                    resp.Summary = StaticUtils.FormatRetVal(retVal, true);
                }
                else if (name == "CeSyncResume" || name == "CeSyncPause")
                {
                    req.Summary = "";

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError, false);

                    resp.Summary = StaticUtils.FormatRetVal(retVal, true);
                }
                else if (name == "CeStartReplication")
                {
                    req.Summary = "";

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError, false);

                    resp.Summary = StaticUtils.FormatBool(retVal);
                }
                else if (name == "CeGetFileAttributes")
                {
                    string fileName = stream.ReadRAPIString(slices);

                    req.AddXMLField("szFileName", fileName,
                        "Name of a file or directory.", slices);

                    req.Summary = String.Format("\"{0}\"", fileName);

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError, false);

                    resp.Summary = StaticUtils.FormatValue(retVal);
                }
                else
                {
                    if (msgLen > 4)
                    {
                        byte[] bytes = stream.ReadBytes((int)msgLen - 4, slices);
                        req.AddField("UnparsedData", StaticUtils.FormatByteArray(bytes), "Unparsed data.", slices);
                    }

                    req.Summary = "[not yet parsed]";

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError, false);

                    resp.Summary = "[not yet parsed]";
                }

                session.AddNode(call);

                stream = session.GetNextStreamDirection();
                if (stream.GetBytesAvailable() == 0)
                    break;
            }
        }
Beispiel #3
0
        private void HandleRapiSession()
        {
            List <PacketSlice> slices = new List <PacketSlice>();
            TransactionNode    node, req, resp;
            string             str;
            UInt32             val, retVal, lastError;

            while (stream.GetBytesAvailable() > 0)
            {
                UInt32             msgLen, msgType;
                List <PacketSlice> msgLenSlices  = new List <PacketSlice>(1);
                List <PacketSlice> msgTypeSlices = new List <PacketSlice>(1);

                // Message length
                msgLen = stream.ReadU32LE(msgLenSlices);

                if (msgLen == 5)
                {
                    node             = new TransactionNode("RAPINotification");
                    node.Description = node.Name;

                    node.AddField("MessageType", "RAPI_NOTIFICATION", "Message type.", msgLenSlices);

                    val = stream.ReadU32LE(slices);
                    node.AddField("NotificationType", (val == 4) ? "REQUEST_NEW_CONNECTION" : StaticUtils.FormatFlags(val), "Notification type.", slices);

                    val = stream.ReadU32LE(slices);
                    node.AddField("Argument", val, "Argument.", slices);

                    session.AddNode(node);

                    if (stream.GetBytesAvailable() < 4)
                    {
                        break;
                    }
                    else
                    {
                        continue;
                    }
                }
                else if (msgLen == 1)
                {
                    node             = new TransactionNode("RAPIKeepalive");
                    node.Description = node.Name;

                    req = new TransactionNode(node, "Request");
                    req.AddField("MessageType", "RAPI_PING", "Message type.", msgLenSlices);

                    stream = session.GetNextStreamDirection();
                    if (stream.GetBytesAvailable() < 4)
                    {
                        break;
                    }

                    stream.ReadU32LE(slices);

                    resp = new TransactionNode(node, "Response");
                    resp.AddField("MessageType", "RAPI_PONG", "Message type.", slices);

                    session.AddNode(node);

                    stream = session.GetNextStreamDirection();

                    if (stream.GetBytesAvailable() < 4)
                    {
                        break;
                    }
                    else
                    {
                        continue;
                    }
                }

                // Message type
                msgType = stream.ReadU32LE(msgTypeSlices);
                if (msgType >= rapiCallNames.Length)
                {
                    logger.AddMessage("Unknown call name: {0:x8}", msgType);
                    return;
                }

                string name = rapiCallNames[msgType];

                RAPICallNode call = new RAPICallNode(name);
                call.Description = call.Name;

                req  = call.Request;
                resp = call.Response;

                req.AddField("MessageLength", msgLen, "Length of the RAPI request.", msgLenSlices);
                req.AddField("MessageType", String.Format("{0} (0x{1:x2})", name, msgType), "Type of the RAPI request.", msgTypeSlices);

                if (name == "CeRegOpenKeyEx")
                {
                    val = stream.ReadU32LE(slices);
                    req.AddField("hKey", StaticUtils.FormatRegKey(val),
                                 "Handle to a currently open key or one of the following predefined reserved handle values:\n" +
                                 "HKEY_CLASSES_ROOT\nHKEY_CURRENT_USER\nHKEY_LOCAL_MACHINE\nHKEY_USERS",
                                 slices);

                    str = stream.ReadRAPIString(slices);
                    req.AddField("szSubKey", str,
                                 "A null-terminated string containing the name of the subkey to open.",
                                 slices);

                    req.Summary = String.Format("{0}, \"{1}\"", StaticUtils.FormatRegKey(val, true), str);

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError);

                    val = stream.ReadU32LE(slices);
                    string result = String.Format("0x{0:x8}", val);
                    resp.AddField("hkResult", result, "Handle to the opened key.", slices);

                    if (retVal == Constants.ERROR_SUCCESS)
                    {
                        resp.Summary = String.Format("{0}, {1}", StaticUtils.FormatRetVal(retVal, true), result);
                    }
                    else
                    {
                        resp.Summary = StaticUtils.FormatRetVal(retVal, true);
                    }
                }
                else if (name == "CeRegCreateKeyEx")
                {
                    val = stream.ReadU32LE(slices);
                    req.AddField("hKey", StaticUtils.FormatRegKey(val),
                                 "Handle to a currently open key or one of the following predefined reserved handle values:\n" +
                                 "HKEY_CLASSES_ROOT\nHKEY_CURRENT_USER\nHKEY_LOCAL_MACHINE\nHKEY_USERS", slices);

                    string szSubKey = stream.ReadRAPIString(slices);
                    req.AddField("szSubKey", (szSubKey != null) ? szSubKey : "(null)",
                                 "A null-terminated string specifying the name of a subkey that this function opens or creates. " +
                                 "The subkey specified must be a subkey of the key identified by the hKey parameter. This subkey " +
                                 "must not begin with the backslash character (\\). If the parameter is NULL, then RegCreateKeyEx " +
                                 "behaves like RegOpenKey, where it opens the key specified by hKey.", slices);

                    string szClass = stream.ReadRAPIString(slices);
                    req.AddField("szClass", (szClass != null) ? szClass : "(null)",
                                 "A null-terminated string that specifies the class (object type) of this key. This parameter is " +
                                 "ignored if the key already exists.", slices);

                    req.Summary = String.Format("{0}, {1}, {2}",
                                                StaticUtils.FormatRegKey(val, true),
                                                StaticUtils.FormatStringArgument(szSubKey),
                                                StaticUtils.FormatStringArgument(szClass));

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError);

                    string result = String.Format("0x{0:x8}", stream.ReadU32LE(slices));
                    resp.AddField("hkResult", result, "Handle to the opened key.", slices);

                    UInt32 disposition = stream.ReadU32LE(slices);
                    resp.AddField("dwDisposition", StaticUtils.FormatRegDisposition(disposition),
                                  "Receives one of REG_CREATED_NEW_KEY and REG_OPENED_EXISTING_KEY.",
                                  slices);

                    if (retVal == Constants.ERROR_SUCCESS)
                    {
                        resp.Summary = String.Format("{0}, {1}, {2}",
                                                     StaticUtils.FormatRetVal(retVal, true), result, StaticUtils.FormatRegDisposition(disposition, true));
                    }
                    else
                    {
                        resp.Summary = StaticUtils.FormatRetVal(retVal, true);
                    }
                }
                else if (name == "CeRegCloseKey")
                {
                    val = stream.ReadU32LE(slices);
                    req.AddField("hKey", StaticUtils.FormatRegKey(val),
                                 "Handle to the open key to close.", slices);

                    req.Summary = StaticUtils.FormatRegKey(val, true);

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError);

                    resp.Summary = StaticUtils.FormatRetVal(retVal, true);
                }
                else if (name == "CeRegQueryValueEx")
                {
                    val = stream.ReadU32LE(slices);
                    req.AddField("hKey", StaticUtils.FormatRegKey(val),
                                 "Handle to a currently open key or any of the following predefined reserved handle values:\n" +
                                 "HKEY_CLASSES_ROOT\nHKEY_CURRENT_USER\nHKEY_LOCAL_MACHINE\nHKEY_USERS", slices);

                    string szValueName = stream.ReadRAPIString(slices);
                    req.AddField("szValueName", szValueName,
                                 "A string containing the name of the value to query.", slices);

                    UInt32 cbData = stream.ReadU32LE(slices);
                    req.AddField("cbData", cbData,
                                 "A variable that specifies the maximum number of bytes to return.", slices);

                    req.Summary = String.Format("{0}, {1}, {2}",
                                                StaticUtils.FormatRegKey(val, true),
                                                StaticUtils.FormatStringArgument(szValueName),
                                                cbData);

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError);

                    UInt32 dwType = stream.ReadU32LE(slices);
                    resp.AddField("dwType", StaticUtils.FormatRegType(dwType),
                                  "The type of data associated with the specified value.",
                                  slices);

                    cbData = stream.ReadU32LE(slices);
                    resp.AddField("cbData", Convert.ToString(cbData),
                                  "The size of the data returned.", slices);

                    str = ReadAndFormatDataForRegType(dwType, cbData, slices);
                    if (str == null)
                    {
                        str = "NULL";
                    }
                    resp.AddField("Data", str, "The data returned.", slices);

                    resp.Summary = StaticUtils.FormatRetVal(retVal, true);
                }
                else if (name == "CeRegSetValueEx")
                {
                    UInt32 key = stream.ReadU32LE(slices);
                    req.AddField("hKey", StaticUtils.FormatRegKey(key),
                                 "Handle to a currently open key or any of the following predefined reserved handle values:\n" +
                                 "HKEY_CLASSES_ROOT\nHKEY_CURRENT_USER\nHKEY_LOCAL_MACHINE\nHKEY_USERS", slices);

                    string szValueName = stream.ReadRAPIString(slices);
                    req.AddField("szValueName", szValueName,
                                 "String containing the name of the value to set. If a value with this name is not already " +
                                 "present in the key, the function adds it to the key. If this parameter is NULL or an empty " +
                                 "string, the function sets the type and data for the key's unnamed value. Registry keys do " +
                                 "not have default values, but they can have one unnamed value, which can be of any type.",
                                 slices);

                    UInt32 dwType = stream.ReadU32LE(slices);
                    req.AddField("dwType", StaticUtils.FormatRegType(dwType),
                                 "Type of information to be stored as the value's data.",
                                 slices);

                    UInt32 cbData = stream.ReadU32LE(slices);
                    req.AddField("cbData", Convert.ToString(cbData),
                                 "Specifies the size, in bytes, of the information passed in the the Data field.",
                                 slices);

                    str = ReadAndFormatDataForRegType(dwType, cbData, slices);
                    if (str == null)
                    {
                        str = "NULL";
                    }
                    req.AddField("Data", str, "Buffer containing the data to be stored with the specified value name.",
                                 slices);

                    string dataSummary;
                    if (dwType == Constants.REG_DWORD || dwType == Constants.REG_DWORD_BIG_ENDIAN)
                    {
                        dataSummary = str;
                    }
                    else
                    {
                        dataSummary = String.Format("[{0} bytes]", cbData);
                    }

                    req.Summary = String.Format("{0}, {1}, {2}, {3}",
                                                StaticUtils.FormatRegKey(key), StaticUtils.FormatStringArgument(szValueName), StaticUtils.FormatRegType(dwType), dataSummary);

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError);

                    resp.Summary = StaticUtils.FormatRetVal(retVal, true);
                }
                else if (name == "CeProcessConfig")
                {
                    str = stream.ReadRAPIString(slices);
                    req.AddXMLField("szRequest", str, "Config request.", slices);

                    UInt32 flags = stream.ReadU32LE(slices);
                    req.AddField("dwFlags", StaticUtils.FormatFlags(flags), "Flags.", slices);

                    req.Summary = String.Format("[{0} bytes], 0x{1:x8}",
                                                str.Length, flags);

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError);

                    str = stream.ReadRAPIString(slices);
                    resp.AddXMLField("szResponse", str, "Config response.", slices);

                    if (retVal == Constants.ERROR_SUCCESS)
                    {
                        resp.Summary = String.Format("{0}, [{1} bytes]",
                                                     StaticUtils.FormatRetVal(retVal, true), (str != null) ? str.Length : 0);
                    }
                    else
                    {
                        resp.Summary = StaticUtils.FormatRetVal(retVal, true);
                    }
                }
                else if (name == "CeGetDesktopDeviceCaps")
                {
                    string caps = FormatDeviceCaps(stream.ReadU32LE(slices));
                    req.AddField("nIndex", caps, "The item to return.", slices);

                    req.Summary = caps;

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError, false);

                    resp.Summary = StaticUtils.FormatValue(retVal);
                }
                else if (name == "CeSyncStart")
                {
                    string xml = stream.ReadRAPIString(slices);
                    req.AddXMLField("szXML", (xml != null) ? xml : "(null)",
                                    "Optional message.", slices);

                    if (xml != null)
                    {
                        req.Summary = String.Format("[{0} bytes]", xml.Length);
                    }
                    else
                    {
                        req.Summary = "NULL";
                    }

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError);

                    resp.Summary = StaticUtils.FormatRetVal(retVal, true);
                }
                else if (name == "CeSyncResume" || name == "CeSyncPause")
                {
                    req.Summary = "";

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError, false);

                    resp.Summary = StaticUtils.FormatRetVal(retVal, true);
                }
                else if (name == "CeStartReplication")
                {
                    req.Summary = "";

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError, false);

                    resp.Summary = StaticUtils.FormatBool(retVal);
                }
                else if (name == "CeGetFileAttributes")
                {
                    string fileName = stream.ReadRAPIString(slices);

                    req.AddXMLField("szFileName", fileName,
                                    "Name of a file or directory.", slices);

                    req.Summary = String.Format("\"{0}\"", fileName);

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError, false);

                    resp.Summary = StaticUtils.FormatValue(retVal);
                }
                else
                {
                    if (msgLen > 4)
                    {
                        byte[] bytes = stream.ReadBytes((int)msgLen - 4, slices);
                        req.AddField("UnparsedData", StaticUtils.FormatByteArray(bytes), "Unparsed data.", slices);
                    }

                    req.Summary = "[not yet parsed]";

                    SwitchToResponseAndParseResult(resp, slices, out retVal, out lastError, false);

                    resp.Summary = "[not yet parsed]";
                }

                session.AddNode(call);

                stream = session.GetNextStreamDirection();
                if (stream.GetBytesAvailable() == 0)
                {
                    break;
                }
            }
        }