1d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// found in the LICENSE file.
4d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
5d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using System;
6d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using System.Collections.Generic;
7d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using System.ComponentModel;
8d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using System.Linq;
9d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using System.Runtime.InteropServices;
10d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using System.Text;
11d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using System.Threading.Tasks;
12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using ChromeDebug.LowLevel;
14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)namespace ChromeDebug {
16d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  internal static class Utility {
17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public static string[] SplitArgs(string unsplitArgumentLine) {
18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (unsplitArgumentLine == null)
19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return new string[0];
20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      int numberOfArgs;
22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      IntPtr ptrToSplitArgs;
23d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      string[] splitArgs;
24d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
25d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      ptrToSplitArgs = NativeMethods.CommandLineToArgvW(unsplitArgumentLine, out numberOfArgs);
26d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
27d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // CommandLineToArgvW returns NULL upon failure.
28d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (ptrToSplitArgs == IntPtr.Zero)
29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        throw new ArgumentException("Unable to split argument.", new Win32Exception());
30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      // Make sure the memory ptrToSplitArgs to is freed, even upon failure.
32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      try {
33d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        splitArgs = new string[numberOfArgs];
34d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
35d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // ptrToSplitArgs is an array of pointers to null terminated Unicode strings.
36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // Copy each of these strings into our split argument array.
37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        for (int i = 0; i < numberOfArgs; i++)
38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          splitArgs[i] = Marshal.PtrToStringUni(
39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)              Marshal.ReadIntPtr(ptrToSplitArgs, i * IntPtr.Size));
40d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
41d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return splitArgs;
42d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      }
43d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      finally {
44d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // Free memory obtained by CommandLineToArgW.
45d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        NativeMethods.LocalFree(ptrToSplitArgs);
46d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      }
47d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
48d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
49d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public static T ReadUnmanagedStructFromProcess<T>(IntPtr processHandle,
50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                                      IntPtr addressInProcess) {
51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      int bytesRead;
52d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      int bytesToRead = Marshal.SizeOf(typeof(T));
53d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      IntPtr buffer = Marshal.AllocHGlobal(bytesToRead);
54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (!NativeMethods.ReadProcessMemory(processHandle, addressInProcess, buffer, bytesToRead,
55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)              out bytesRead))
56d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        throw new Win32Exception();
57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      T result = (T)Marshal.PtrToStructure(buffer, typeof(T));
58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      Marshal.FreeHGlobal(buffer);
59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return result;
60d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
61d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
62d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public static string ReadStringUniFromProcess(IntPtr processHandle,
63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                                  IntPtr addressInProcess,
64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                                  int NumChars) {
65d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      int bytesRead;
66d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      IntPtr outBuffer = Marshal.AllocHGlobal(NumChars * 2);
67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
68d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      bool bresult = NativeMethods.ReadProcessMemory(processHandle,
69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                                     addressInProcess,
70d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                                     outBuffer,
71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                                     NumChars * 2,
72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                                     out bytesRead);
73d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (!bresult)
74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        throw new Win32Exception();
75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
76d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      string result = Marshal.PtrToStringUni(outBuffer, bytesRead / 2);
77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      Marshal.FreeHGlobal(outBuffer);
78d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return result;
79d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
80d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
81d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public static int UnmanagedStructSize<T>() {
82d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return Marshal.SizeOf(typeof(T));
83d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
84d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
85d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
86