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