PageRenderTime 24ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/Code/Foundation/Windows/Win32Api.cs

https://github.com/DavidMoore/Foundation
C# | 293 lines | 115 code | 33 blank | 145 comment | 4 complexity | e1965ae9823d1fe5f463b0bb6ba3a3db MD5 | raw file
  1. using System;
  2. using System.Runtime.ConstrainedExecution;
  3. using System.Runtime.InteropServices;
  4. using System.Runtime.InteropServices.ComTypes;
  5. using System.Runtime.Versioning;
  6. using System.Text;
  7. using Foundation.Windows.IO;
  8. using Microsoft.Win32.SafeHandles;
  9. namespace Foundation.Windows
  10. {
  11. /// <summary>
  12. /// Win32 API interop functions through P/Invoke.
  13. /// </summary>
  14. public static class Win32Api
  15. {
  16. const string advancedWindows32BaseApi = "advapi32.dll";
  17. const string kernel32ClientBaseApi = "kernel32.dll";
  18. const string oleForWindowsApi = "ole32.dll";
  19. const string user32 = "user32.dll";
  20. public static class Threading
  21. {
  22. /// <summary>
  23. /// Attaches or detaches the input processing mechanism of one thread to that of another thread.
  24. /// </summary>
  25. /// <param name="threadToBeAttached">The identifier of the thread to be attached to another thread. The thread to be attached cannot be a system thread.</param>
  26. /// <param name="threadToBeAttachedTo">
  27. /// <p>The identifier of the thread to which threadToBeAttached will be attached.This thread cannot be a system thread. </p>
  28. /// <p>A thread cannot attach to itself. Therefore, <paramref name="threadToBeAttachedTo"/> cannot equal <paramref name="threadToBeAttached"/>.</p>
  29. /// </param>
  30. /// <param name="attach">If this parameter is <c>true</c>, the two threads are attached. If the parameter is <c>false</c>, the threads are detached.</param>
  31. /// <returns>
  32. /// <p>If the function succeeds, the return value is nonzero.</p>
  33. /// <p>If the function fails, the return value is zero. To get extended error information, call <see cref="Marshal.GetLastWin32Error"/>.</p>
  34. /// </returns>
  35. /// <remarks>
  36. /// <p>Windows created in different threads typically process input independently of each other. That is, they have their own input states (focus, active, capture windows, key state, queue status, and so on), and their input processing is not synchronized with the input processing of other threads. By using the AttachThreadInput function, a thread can attach its input processing mechanism to another thread. Keyboard and mouse events received by both threads are processed by the thread specified by the idAttachTo parameter until the threads are detached by calling AttachThreadInput a second time and specifying FALSE for the fAttach parameter. This also allows threads to share their input states, so they can call the SetFocus function to set the keyboard focus to a window of a different thread. This also allows threads to get key-state information.</p>
  37. /// <p>The AttachThreadInput function fails if either of the specified threads does not have a message queue. The system creates a thread's message queue when the thread makes its first call to one of the USER or GDI functions. The AttachThreadInput function also fails if a journal record hook is installed. Journal record hooks attach all input queues together.</p>
  38. /// <p>Note that key state, which can be ascertained by calls to the GetKeyState or GetKeyboardState function, is reset after a call to AttachThreadInput. You cannot attach a thread to a thread in another desktop.</p>
  39. /// </remarks>
  40. [DllImport(user32)]
  41. static extern bool AttachThreadInput(uint threadToBeAttached, uint threadToBeAttachedTo, bool attach);
  42. [DllImport(user32)]
  43. public static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr processId);
  44. [DllImport(kernel32ClientBaseApi)]
  45. static extern uint GetCurrentThreadId();
  46. }
  47. public static class Windows
  48. {
  49. [DllImport(user32)]
  50. [return: MarshalAs(UnmanagedType.Bool)]
  51. public static extern bool SetForegroundWindow(IntPtr hWnd);
  52. [DllImport(user32)]
  53. static extern IntPtr SetFocus(IntPtr hWnd);
  54. }
  55. /// <summary>
  56. /// Contains functions for manipulating the Windows registry.
  57. /// </summary>
  58. public static class Registry
  59. {
  60. /// <summary>
  61. /// Override a registry hive key to another registry key.
  62. /// </summary>
  63. /// <param name="key">Handle of the key to override.</param>
  64. /// <param name="newKey">Handle to override key.</param>
  65. internal static void RedirectRegistryKey(SafeRegistryHandle key, SafeRegistryHandle newKey)
  66. {
  67. if (0 != RegOverridePredefKey(key, newKey))
  68. {
  69. throw new Exception();
  70. }
  71. }
  72. /// <summary>
  73. /// Interop to RegOverridePredefKey.
  74. /// </summary>
  75. /// <param name="key">Handle to key to override.</param>
  76. /// <param name="newKey">Handle to override key.</param>
  77. /// <returns>0 if success.</returns>
  78. [DllImport(advancedWindows32BaseApi, EntryPoint = "RegOverridePredefKey", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
  79. static extern int RegOverridePredefKey(SafeRegistryHandle key, SafeRegistryHandle newKey);
  80. }
  81. /// <summary>
  82. /// Contains functions for file system operations.
  83. /// </summary>
  84. public static class IO
  85. {
  86. /// <summary>
  87. /// Moves an existing file or directory, including its children, with various move options.
  88. /// </summary>
  89. /// <param name="existingFileName">
  90. /// <p>The current name of the file or directory on the local computer.</p>
  91. /// <p>If <paramref name="moveFileFlags"/> specifies <see cref="MoveFileFlags.DelayUntilReboot"/>,
  92. /// the file cannot exist on a remote share, because delayed operations are performed
  93. /// before the network is available.</p>
  94. /// </param>
  95. /// <param name="newFileName">
  96. /// <p>The new name of the file or directory on the local computer.</p>
  97. /// <p>When moving a file, the destination can be on a different file system or volume.
  98. /// If the destination is on another drive, you must set the <see cref="MoveFileFlags.CopyAllowed"/> flag in <paramref name="moveFileFlags"/>.</p>
  99. /// <p>When moving a directory, the destination must be on the same drive.</p>
  100. /// <p>If <paramref name="moveFileFlags"/> specifies <see cref="MoveFileFlags.DelayUntilReboot"/> and <paramref name="newFileName"/> is <c>null</c>, <see cref="MoveFileEx"/> registers the <paramref name="existingFileName"/> file to be deleted when the system restarts.
  101. /// If <paramref name="existingFileName"/> refers to a directory, the system removes the directory at restart only if the directory is empty.</p>
  102. /// </param>
  103. /// <param name="moveFileFlags">The options flags for the file or directory move. See <see cref="MoveFileFlags"/>.</param>
  104. /// <returns>
  105. /// <p>If the function succeeds, the return value is nonzero.</p>
  106. /// <p>If the function fails, the return value is zero (0). To get extended error information, call <see cref="Marshal.GetLastWin32Error"/>.</p>
  107. /// </returns>
  108. [DllImport(kernel32ClientBaseApi, SetLastError = true, CharSet = CharSet.Unicode)]
  109. internal static extern bool MoveFileEx(string existingFileName, string newFileName, MoveFileFlags moveFileFlags);
  110. /// <summary>
  111. /// Flags for specifying options to <see cref="MoveFileEx"/>.
  112. /// </summary>
  113. [Flags]
  114. internal enum MoveFileFlags
  115. {
  116. /// <summary>
  117. /// <p>If a file named lpNewFileName exists, the function replaces its contents with the contents of the
  118. /// lpExistingFileName file, provided that security requirements regarding access control lists (ACLs) are met.
  119. /// For more information, see the Remarks section of this topic.</p>
  120. /// <p>This value cannot be used if newFileName or existingFileName names a directory.</p>
  121. /// </summary>
  122. ReplaceExisting = 0x00000001,
  123. /// <summary>
  124. /// If the file is to be moved to a different volume, the function simulates the move by using the
  125. /// CopyFile and DeleteFile functions.
  126. /// <p>This value cannot be used with <see cref="DelayUntilReboot"/>.</p>
  127. /// </summary>
  128. CopyAllowed = 0x00000002,
  129. /// <summary>
  130. /// <p>The system does not move the file until the operating system is restarted.
  131. /// The system moves the file immediately after AUTOCHK is executed, but before creating any paging files.
  132. /// Consequently, this parameter enables the function to delete paging files from previous startups.</p>
  133. /// <p>This value can be used only if the process is in the context of a user who belongs to the
  134. /// administrators group or the LocalSystem account.</p>
  135. /// <p>This value cannot be used with <see cref="CopyAllowed"/>.</p>
  136. /// </summary>
  137. DelayUntilReboot = 0x00000004,
  138. /// <summary>
  139. /// <p>The function does not return until the file is actually moved on the disk.</p>
  140. /// <p>Setting this value guarantees that a move performed as a copy and delete operation
  141. /// is flushed to disk before the function returns. The flush occurs at the end of the copy operation.</p>
  142. /// <p>This value has no effect if <see cref="DelayUntilReboot"/> is set.</p>
  143. /// </summary>
  144. WriteThrough = 0x00000008,
  145. /// <summary>
  146. /// Reserved for future use.
  147. /// </summary>
  148. CreateHardlink = 0x00000010,
  149. /// <summary>
  150. /// The function fails if the source file is a link source, but the file cannot be tracked after the move.
  151. /// This situation can occur if the destination is a volume formatted with the FAT file system.
  152. /// </summary>
  153. FailIfNotTrackable = 0x00000020
  154. }
  155. [DllImport(kernel32ClientBaseApi, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
  156. [ResourceExposure(ResourceScope.Machine)]
  157. internal static extern int GetLongPathName(String path, StringBuilder longPathBuffer, int bufferLength);
  158. [DllImport(kernel32ClientBaseApi, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
  159. [ResourceExposure(ResourceScope.Machine)]
  160. internal unsafe static extern int GetLongPathName(char* path, char* longPathBuffer, int bufferLength);
  161. [DllImport(kernel32ClientBaseApi, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
  162. [ResourceExposure(ResourceScope.None)]
  163. internal static extern SafeFindHandle FindFirstFile(String fileName, [In, Out] FindData data);
  164. [DllImport(kernel32ClientBaseApi, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
  165. [ResourceExposure(ResourceScope.None)]
  166. [return: MarshalAs(UnmanagedType.Bool)]
  167. internal static extern bool FindNextFile(SafeFindHandle hndFindFile, [In, Out, MarshalAs(UnmanagedType.LPStruct)] FindData lpFindFileData);
  168. [DllImport(kernel32ClientBaseApi)]
  169. [ResourceExposure(ResourceScope.None)]
  170. [return: MarshalAs(UnmanagedType.Bool)]
  171. [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  172. internal static extern bool FindClose(IntPtr handle);
  173. }
  174. /// <summary>
  175. /// COM and OLE functions.
  176. /// </summary>
  177. public static class Com
  178. {
  179. /// <summary>
  180. /// Returns a pointer to the <see cref="IRunningObjectTable"/> interface on the local running object table (ROT).
  181. /// </summary>
  182. /// <param name="reserved">This parameter is reserved and must be 0.</param>
  183. /// <param name="runningObjectTable">
  184. /// The address of an <see cref="IRunningObjectTable"/>* pointer variable that receives the
  185. /// interface pointer to the local ROT. When the function is successful, the caller is responsible
  186. /// for calling <see cref="IUnknown.Release"/> on the interface pointer. If an error occurs, *runningObjectTable is undefined.
  187. /// </param>
  188. /// <returns></returns>
  189. [DllImport(oleForWindowsApi)]
  190. private static extern int GetRunningObjectTable(uint reserved, out IRunningObjectTable runningObjectTable);
  191. /// <summary>
  192. /// Returns a pointer to an implementation of <see cref="IBindCtx"/> (a bind context object).
  193. /// This object stores information about a particular moniker-binding operation.
  194. /// </summary>
  195. /// <param name="reserved">This parameter is reserved and must be 0.</param>
  196. /// <param name="ppbc">
  197. /// Address of an <see cref="IBindCtx"/>* pointer variable that receives the interface pointer to the new bind context object.
  198. /// When the function is successful, the caller is responsible for calling <see cref="IUnknown.Release"/> on the bind context.
  199. /// A <c>null</c> value for the bind context indicates that an error occurred.</param>
  200. /// <returns></returns>
  201. [DllImport(oleForWindowsApi)]
  202. private static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc);
  203. }
  204. /// <summary>
  205. /// Loads a module into this process.
  206. /// </summary>
  207. /// <param name="file">The file to load.</param>
  208. /// <returns>A handle to the loaded module.</returns>
  209. public static SafeLibraryHandle LoadLibrary(string file)
  210. {
  211. var handle = LoadLibraryEx(file, IntPtr.Zero, LoadLibraryExFlags.LoadWithAlteredSearchPath);
  212. if (handle == null) throw new LoadLibraryException(file, Marshal.GetLastWin32Error());
  213. return handle;
  214. }
  215. /// <summary>
  216. /// Loads a dynamic link library into this process.
  217. /// </summary>
  218. /// <remarks>Loads the specified module into the address space of the calling process. The specified module may cause other modules to be loaded.</remarks>
  219. /// <param name="fileName">The name of the module.</param>
  220. /// <param name="reserved">This parameter is reserved for future use. It must be null (set to <see cref="IntPtr.Zero"/>).</param>
  221. /// <param name="flags">The action to be taken when loading the module.</param>
  222. /// <returns>
  223. /// If the function succeeds, the return value is a handle to the loaded module.
  224. /// If the function fails, the return value is NULL. To get extended error information, call <see cref="Marshal.GetLastWin32Error"/>.
  225. /// </returns>
  226. [DllImport(kernel32ClientBaseApi, CharSet = CharSet.Unicode, SetLastError = true)]
  227. internal static extern SafeLibraryHandle LoadLibraryEx(string fileName, IntPtr reserved, LoadLibraryExFlags flags);
  228. /// <summary>
  229. /// Frees the loaded dynamic-link library (DLL) module and, if necessary, decrements its reference count.
  230. /// When the reference count reaches zero, the module is unloaded from the address space of the calling process and the handle is no longer valid.
  231. /// </summary>
  232. /// <param name="moduleHandle">A handle to the loaded library module. The <see cref="LoadLibraryEx"/> function returns this handle.</param>
  233. /// <returns></returns>
  234. [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  235. [DllImport(kernel32ClientBaseApi, CharSet = CharSet.Unicode)]
  236. [return: MarshalAs(UnmanagedType.Bool)]
  237. internal static extern bool FreeLibrary(IntPtr moduleHandle);
  238. [DllImport(kernel32ClientBaseApi, SetLastError = false)]
  239. [ResourceExposure(ResourceScope.Process)]
  240. internal static extern int SetErrorMode(int newMode);
  241. // TODO: Make into an enum
  242. /// <summary>
  243. /// <p>The system does not display the critical-error-handler message box. Instead, the system sends the error to the calling process.</p>
  244. /// <p>Best practice is that all applications call the process-wide <see cref="SetErrorMode"/> function with a parameter of <see cref="FailCriticalErrors"/> at startup. This is to prevent error mode dialogs from hanging the application.</p>
  245. /// </summary>
  246. internal const int FailCriticalErrors = 1;
  247. [DllImport(kernel32ClientBaseApi, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
  248. [ResourceExposure(ResourceScope.Machine)]
  249. internal unsafe static extern int GetFullPathName(char* path, int numBufferChars, char* buffer, IntPtr mustBeZero);
  250. [DllImport(kernel32ClientBaseApi, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
  251. [ResourceExposure(ResourceScope.Machine)]
  252. internal unsafe static extern int GetFullPathName(String path, int numBufferChars, StringBuilder buffer, IntPtr mustBeZero);
  253. [DllImport(kernel32ClientBaseApi, CharSet = CharSet.Unicode)]
  254. [ResourceExposure(ResourceScope.None)]
  255. internal static extern int FormatMessage(int dwFlags, IntPtr lpSource,
  256. int dwMessageId, int dwLanguageId, StringBuilder lpBuffer,
  257. int nSize, IntPtr vaListArguments);
  258. internal static readonly IntPtr Null = IntPtr.Zero;
  259. }
  260. }