MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Diagnostics.CodeAnalysis;5using System.Runtime.InteropServices;6 7using Microsoft.Win32.SafeHandles;8 9namespace System.Management.Automation10{11 internal static class PlatformInvokes12 {13 [StructLayout(LayoutKind.Sequential)]14 internal sealed class FILETIME15 {16 internal uint dwLowDateTime;17 internal uint dwHighDateTime;18 19 internal FILETIME()20 {21 dwLowDateTime = 0;22 dwHighDateTime = 0;23 }24 25 internal FILETIME(long fileTime)26 {27 dwLowDateTime = (uint)fileTime;28 dwHighDateTime = (uint)(fileTime >> 32);29 }30 31 public long ToTicks()32 {33 return ((long)dwHighDateTime << 32) + dwLowDateTime;34 }35 }36 37 [Flags]38 // dwDesiredAccess of CreateFile39 internal enum FileDesiredAccess : uint40 {41 GenericRead = 0x80000000,42 GenericWrite = 0x40000000,43 GenericExecute = 0x20000000,44 GenericAll = 0x10000000,45 }46 47 [Flags]48 // dwShareMode of CreateFile49 internal enum FileShareMode : uint50 {51 None = 0x00000000,52 Read = 0x00000001,53 Write = 0x00000002,54 Delete = 0x00000004,55 }56 57 // dwCreationDisposition of CreateFile58 internal enum FileCreationDisposition : uint59 {60 New = 1,61 CreateAlways = 2,62 OpenExisting = 3,63 OpenAlways = 4,64 TruncateExisting = 5,65 }66 67 [Flags]68 // dwFlagsAndAttributes69 internal enum FileAttributes : uint70 {71 ReadOnly = 0x00000001,72 Hidden = 0x00000002,73 System = 0x00000004,74 Directory = 0x00000010,75 Archive = 0x00000020,76 Normal = 0x00000080,77 Temporary = 0x00000100,78 Offline = 0x00001000,79 NotContentIndexed = 0x00002000,80 Encrypted = 0x00004000,81 Write_Through = 0x80000000,82 Overlapped = 0x40000000,83 NoBuffering = 0x20000000,84 RandomAccess = 0x10000000,85 SequentialScan = 0x08000000,86 DeleteOnClose = 0x04000000,87 BackupSemantics = 0x02000000,88 PosixSemantics = 0x01000000,89 OpenReparsePoint = 0x00200000,90 OpenNoRecall = 0x00100000,91 SessionAware = 0x0080000092 }93 94 [StructLayout(LayoutKind.Sequential)]95 internal sealed class SecurityAttributes96 {97 internal int nLength;98 internal SafeLocalMemHandle lpSecurityDescriptor;99 internal bool bInheritHandle;100 101 internal SecurityAttributes()102 {103 this.nLength = 12;104 this.bInheritHandle = true;105 this.lpSecurityDescriptor = new SafeLocalMemHandle(IntPtr.Zero, true);106 }107 }108 109 internal sealed class SafeLocalMemHandle : SafeHandleZeroOrMinusOneIsInvalid110 {111 // Methods112 internal SafeLocalMemHandle()113 : base(true)114 {115 }116 117 internal SafeLocalMemHandle(IntPtr existingHandle, bool ownsHandle)118 : base(ownsHandle)119 {120 base.SetHandle(existingHandle);121 }122 123 [DllImport(PinvokeDllNames.LocalFreeDllName)]124 private static extern IntPtr LocalFree(IntPtr hMem);125 126 protected override bool ReleaseHandle()127 {128 return (LocalFree(base.handle) == IntPtr.Zero);129 }130 }131 132 /// <summary>133 /// Creates or opens a file, file stream, directory, physical disk, volume, console buffer,134 /// tape drive, communications resource, mailslot, or named pipe. The function returns a135 /// handle that can be used to access the object.136 /// </summary>137 /// <param name="lpFileName">138 /// The name of the object to be created or opened.139 /// In the ANSI version of this function, the name is limited to MAX_PATH characters.140 /// To extend this limit to 32,767 wide characters, call the Unicode version of the141 /// function and prepend "\\?\" to the path. For more information, see Naming a File.142 /// For information on special device names, see Defining an MS-DOS Device Name.143 /// To specify a COM port number greater than 9, use the following syntax: "\\.\COM10".144 /// This syntax works for all port numbers and hardware that allows COM port numbers to be specified.145 /// To create a file stream, specify the name of the file, a colon, and then the name of the146 /// stream. For more information, see File Streams.147 /// </param>148 /// <param name="dwDesiredAccess">149 /// The access to the object, which can be read, write, or both.150 /// You cannot request an access mode that conflicts with the sharing mode that is151 /// specified in an open request that has an open handle.152 /// If this parameter is zero (0), the application can query file and device attributes153 /// without accessing a device. This is useful for an application to determine the size154 /// of a floppy disk drive and the formats it supports without requiring a floppy in a drive.155 /// It can also be used to test for the existence of a file or directory without opening156 /// them for read or write access.157 /// See the "CreateFile desired access" below.158 /// </param>159 /// <param name="dwShareMode">160 /// The sharing mode of an object, which can be read, write, both, or none.161 /// You cannot request a sharing mode that conflicts with the access mode that is specified162 /// in an open request that has an open handle, because that would result in the following163 /// sharing violation: ERROR_SHARING_VIOLATION.164 /// If this parameter is zero (0) and CreateFile succeeds, the object cannot be shared165 /// and cannot be opened again until the handle is closed. For more information, see the166 /// Remarks section of this topic.167 /// The sharing options remain in effect until you close the handle to an object.168 /// To enable a process to share an object while another process has the object open,169 /// use a combination of one or more of the following values to specify the access mode170 /// they can request to open the object.171 /// </param>172 /// <param name="lpSecurityAttributes">173 /// A pointer to a SECURITY_ATTRIBUTES structure that determines whether or not the returned174 /// handle can be inherited by child processes.175 /// If lpSecurityAttributes is NULL, the handle cannot be inherited.176 /// The lpSecurityDescriptor member of the structure specifies a security descriptor177 /// for an object. If lpSecurityAttributes is NULL, the object gets a default security descriptor.178 /// The access control lists (ACL) in the default security descriptor for a file or directory179 /// are inherited from its parent directory.180 /// The target file system must support security on files and directories for this parameter to181 /// have an effect on them, which is indicated when GetVolumeInformation returns FS_PERSISTENT_ACLS.182 /// CreateFile ignores lpSecurityDescriptor when opening an existing file, but continues to183 /// use the other structure members.184 /// </param>185 /// <param name="dwCreationDisposition">186 /// An action to take on files that exist and do not exist.187 /// See "CreateFile creation disposition" below188 /// </param>189 /// <param name="dwFlagsAndAttributes">190 /// The file attributes and flags.191 /// This parameter can include any combination of the file attributes.192 /// All other file attributes override FILE_ATTRIBUTE_NORMAL.193 /// When CreateFile opens a file, it combines the file flags with existing194 /// file attributes, and ignores any supplied file attributes.195 /// </param>196 /// <param name="hTemplateFile">197 /// A handle to a template file with the GENERIC_READ access right.198 /// The template file supplies file attributes and extended attributes for the file that is199 /// being created. This parameter can be NULL.200 /// When opening an existing file, CreateFile ignores the template file.201 /// When opening a new EFS-encrypted file, the file inherits the DACL from its parent directory.202 /// </param>203 /// <returns>204 /// If the function succeeds, the return value is an open handle to a specified file.205 /// If a specified file exists before the function call and dwCreationDisposition is CREATE_ALWAYS206 /// or OPEN_ALWAYS, a call to GetLastError returns ERROR_ALREADY_EXISTS, even when the207 /// function succeeds. If a file does not exist before the call, GetLastError returns zero (0).208 /// If the function fails, the return value is INVALID_HANDLE_VALUE.209 /// To get extended error information, call GetLastError.210 /// </returns>211 [DllImport(PinvokeDllNames.CreateFileDllName, SetLastError = true, CharSet = CharSet.Unicode)]212 internal static extern IntPtr CreateFile(213 string lpFileName,214 FileDesiredAccess dwDesiredAccess,215 FileShareMode dwShareMode,216 IntPtr lpSecurityAttributes,217 FileCreationDisposition dwCreationDisposition,218 FileAttributes dwFlagsAndAttributes,219 IntPtr hTemplateFile);220 221 /// <summary>222 /// Closes an open object handle.223 /// </summary>224 /// <param name="handle">225 /// A valid handle to an open object.226 /// </param>227 /// <returns>228 /// If the function succeeds, the return value is nonzero.229 /// If the function fails, the return value is zero. To get extended error information,230 /// call GetLastError.231 /// If the application is running under a debugger, the function will throw an exception232 /// if it receives either a handle value that is not valid or a pseudo-handle value.233 /// This can happen if you close a handle twice, or if you call CloseHandle on a handle234 /// returned by the FindFirstFile function.235 /// </returns>236 [DllImport(PinvokeDllNames.CloseHandleDllName, SetLastError = true)]237 [return: MarshalAs(UnmanagedType.Bool)]238 internal static extern bool CloseHandle(IntPtr handle);239 240 [DllImport(PinvokeDllNames.DosDateTimeToFileTimeDllName, SetLastError = false)]241 [return: MarshalAs(UnmanagedType.Bool)]242 internal static extern bool DosDateTimeToFileTime(243 short wFatDate, // _In_ WORD244 short wFatTime, // _In_ WORD245 FILETIME lpFileTime); // _Out_ LPFILETIME246 247 [DllImport(PinvokeDllNames.LocalFileTimeToFileTimeDllName, SetLastError = false, CharSet = CharSet.Unicode)]248 [return: MarshalAs(UnmanagedType.Bool)]249 internal static extern bool LocalFileTimeToFileTime(250 FILETIME lpLocalFileTime, // _In_ const FILETIME *251 FILETIME lpFileTime); // _Out_ LPFILETIME252 253 [DllImport(PinvokeDllNames.SetFileTimeDllName, SetLastError = false, CharSet = CharSet.Unicode)]254 [return: MarshalAs(UnmanagedType.Bool)]255 internal static extern bool SetFileTime(256 IntPtr hFile, // _In_ HANDLE257 FILETIME lpCreationTime, // _In_opt_ const FILETIME *258 FILETIME lpLastAccessTime, // _In_opt_ const FILETIME *259 FILETIME lpLastWriteTime); // _In_opt_ const FILETIME *260 261 [DllImport(PinvokeDllNames.SetFileAttributesWDllName, SetLastError = false, CharSet = CharSet.Unicode)]262 [return: MarshalAs(UnmanagedType.Bool)]263 internal static extern bool SetFileAttributesW(264 [MarshalAs(UnmanagedType.LPWStr)] string lpFileName, // _In_ LPCTSTR265 FileAttributes dwFileAttributes); // _In_ DWORD266 267 /// <summary>268 /// Enable the privilege specified by the privilegeName. If the specified privilege is already enabled, return true269 /// with the oldPrivilegeState.PrivilegeCount set to 0. Otherwise, enable the specified privilege, and the old privilege270 /// state will be saved in oldPrivilegeState.271 /// </summary>272 /// <param name="privilegeName"></param>273 /// <param name="oldPrivilegeState"></param>274 /// <returns></returns>275 internal static bool EnableTokenPrivilege(string privilegeName, ref TOKEN_PRIVILEGE oldPrivilegeState)276 {277 bool success = false;278 TOKEN_PRIVILEGE newPrivilegeState = new TOKEN_PRIVILEGE();279 280 // Check if the caller has the specified privilege or not281 if (LookupPrivilegeValue(null, privilegeName, ref newPrivilegeState.Privilege.Luid))282 {283 // Get the pseudo handler of the current process284 IntPtr processHandler = GetCurrentProcess();285 if (processHandler != IntPtr.Zero)286 {287 // Get the handler of the current process's access token288 IntPtr tokenHandler = IntPtr.Zero;289 if (OpenProcessToken(processHandler, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out tokenHandler))290 {291 // Check if the specified privilege is already enabled292 PRIVILEGE_SET requiredPrivilege = new PRIVILEGE_SET();293 requiredPrivilege.Privilege.Luid = newPrivilegeState.Privilege.Luid;294 requiredPrivilege.PrivilegeCount = 1;295 // PRIVILEGE_SET_ALL_NECESSARY is defined as 1296 requiredPrivilege.Control = 1;297 bool privilegeEnabled = false;298 299 if (PrivilegeCheck(tokenHandler, ref requiredPrivilege, out privilegeEnabled) && privilegeEnabled)300 {301 // The specified privilege is already enabled302 oldPrivilegeState.PrivilegeCount = 0;303 success = true;304 }305 else306 {307 // The specified privilege is not enabled yet. Enable it.308 newPrivilegeState.PrivilegeCount = 1;309 newPrivilegeState.Privilege.Attributes = SE_PRIVILEGE_ENABLED;310 int bufferSize = Marshal.SizeOf<TOKEN_PRIVILEGE>();311 int returnSize = 0;312 313 // enable the specified privilege314 if (AdjustTokenPrivileges(tokenHandler, false, ref newPrivilegeState, bufferSize, out oldPrivilegeState, ref returnSize))315 {316 // AdjustTokenPrivileges returns true does not mean all specified privileges have been successfully enabled317 int retCode = Marshal.GetLastWin32Error();318 if (retCode == ERROR_SUCCESS)319 {320 success = true;321 }322 else if (retCode == 1300)323 {324 // 1300 - Not all privileges referenced are assigned to the caller. This means the specified privilege is not325 // assigned to the current user. For example, suppose the role of current caller is "User", then privilege "SeRemoteShutdownPrivilege"326 // is not assigned to the role. In this case, we just return true and leave the call to "Win32Shutdown" to decide327 // whether the permission is granted or not.328 // Set oldPrivilegeState.PrivilegeCount to 0 to avoid the privilege restore later (PrivilegeCount - how many privileges are modified)329 oldPrivilegeState.PrivilegeCount = 0;330 success = true;331 }332 }333 }334 }335 336 // Close the token handler and the process handler337 if (tokenHandler != IntPtr.Zero)338 {339 CloseHandle(tokenHandler);340 }341 342 CloseHandle(processHandler);343 }344 }345 346 return success;347 }348 349 /// <summary>350 /// Restore the previous privilege state.351 /// </summary>352 /// <param name="privilegeName"></param>353 /// <param name="previousPrivilegeState"></param>354 /// <returns></returns>355 internal static bool RestoreTokenPrivilege(string privilegeName, ref TOKEN_PRIVILEGE previousPrivilegeState)356 {357 // The privilege was not changed, do not need to restore it.358 if (previousPrivilegeState.PrivilegeCount == 0)359 {360 return true;361 }362 363 bool success = false;364 TOKEN_PRIVILEGE newState = new TOKEN_PRIVILEGE();365 366 // Check if the caller has the specified privilege or not. If the caller has it, check the LUID specified in previousPrivilegeState367 // to see if the previousPrivilegeState is defined for the same privilege368 if (LookupPrivilegeValue(null, privilegeName, ref newState.Privilege.Luid) &&369 newState.Privilege.Luid.HighPart == previousPrivilegeState.Privilege.Luid.HighPart &&370 newState.Privilege.Luid.LowPart == previousPrivilegeState.Privilege.Luid.LowPart)371 {372 // Get the pseudo handler of the current process373 IntPtr processHandler = GetCurrentProcess();374 if (processHandler != IntPtr.Zero)375 {376 // Get the handler of the current process's access token377 IntPtr tokenHandler = IntPtr.Zero;378 if (OpenProcessToken(processHandler, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out tokenHandler))379 {380 int bufferSize = Marshal.SizeOf<TOKEN_PRIVILEGE>();381 int returnSize = 0;382 383 // restore the privilege state back to the previous privilege state384 if (AdjustTokenPrivileges(tokenHandler, false, ref previousPrivilegeState, bufferSize, out newState, ref returnSize))385 {386 if (Marshal.GetLastWin32Error() == ERROR_SUCCESS)387 {388 success = true;389 }390 }391 }392 393 if (tokenHandler != IntPtr.Zero)394 {395 CloseHandle(tokenHandler);396 }397 398 CloseHandle(processHandler);399 }400 }401 402 return success;403 }404 405 /// <summary>406 /// The LookupPrivilegeValue function retrieves the locally unique identifier (LUID) used on a specified system to locally represent407 /// the specified privilege name.408 /// </summary>409 /// <param name="lpSystemName"></param>410 /// <param name="lpName"></param>411 /// <param name="lpLuid"></param>412 /// <returns></returns>413 [DllImport(PinvokeDllNames.LookupPrivilegeValueDllName, CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false)]414 [return: MarshalAs(UnmanagedType.Bool)]415 internal static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, ref LUID lpLuid);416 417 /// <summary>418 /// The PrivilegeCheck function determines whether a specified privilege is enabled in an access token.419 /// </summary>420 /// <param name="tokenHandler"></param>421 /// <param name="requiredPrivileges"></param>422 /// <param name="pfResult"></param>423 /// <returns></returns>424 [DllImport(PinvokeDllNames.PrivilegeCheckDllName, CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false)]425 [return: MarshalAs(UnmanagedType.Bool)]426 internal static extern bool PrivilegeCheck(IntPtr tokenHandler, ref PRIVILEGE_SET requiredPrivileges, out bool pfResult);427 428 /// <summary>429 /// The AdjustTokenPrivileges function enables or disables privileges in the specified access token. Enabling or disabling privileges in430 /// an access token requires TOKEN_ADJUST_PRIVILEGES access. The TOKEN_ADJUST_PRIVILEGES and TOKEN_QUERY accesses are gained when calling431 /// the OpenProcessToken function.432 /// </summary>433 /// <param name="tokenHandler"></param>434 /// <param name="disableAllPrivilege"></param>435 /// <param name="newPrivilegeState"></param>436 /// <param name="bufferLength"></param>437 /// <param name="previousPrivilegeState"></param>438 /// <param name="returnLength"></param>439 /// <returns></returns>440 [DllImport(PinvokeDllNames.AdjustTokenPrivilegesDllName, CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false)]441 [return: MarshalAs(UnmanagedType.Bool)]442 internal static extern bool AdjustTokenPrivileges(IntPtr tokenHandler, bool disableAllPrivilege,443 ref TOKEN_PRIVILEGE newPrivilegeState, int bufferLength,444 out TOKEN_PRIVILEGE previousPrivilegeState,445 ref int returnLength);446 447 [StructLayout(LayoutKind.Sequential)]448 internal struct TOKEN_PRIVILEGE449 {450 internal uint PrivilegeCount;451 internal LUID_AND_ATTRIBUTES Privilege;452 }453 454 [StructLayout(LayoutKind.Sequential)]455 internal struct LUID456 {457 internal uint LowPart;458 internal uint HighPart;459 }460 461 [StructLayout(LayoutKind.Sequential)]462 internal struct LUID_AND_ATTRIBUTES463 {464 internal LUID Luid;465 internal uint Attributes;466 }467 468 [StructLayout(LayoutKind.Sequential)]469 internal struct PRIVILEGE_SET470 {471 internal uint PrivilegeCount;472 internal uint Control;473 internal LUID_AND_ATTRIBUTES Privilege;474 }475 476 /// <summary>477 /// Get the pseudo handler of the current process.478 /// </summary>479 /// <returns></returns>480 [DllImport(PinvokeDllNames.GetCurrentProcessDllName)]481 internal static extern IntPtr GetCurrentProcess();482 483 /// <summary>484 /// Retrieves the current process token.485 /// This function exists just for backward compatibility. It is preferred to use the other override that takes 'SafeHandle' as parameter.486 /// </summary>487 /// <param name="processHandle">Process handle.</param>488 /// <param name="desiredAccess">Token access.</param>489 /// <param name="tokenHandle">Process token.</param>490 /// <returns>The current process token.</returns>491 [DllImport(PinvokeDllNames.OpenProcessTokenDllName, CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false)]492 [return: MarshalAs(UnmanagedType.Bool)]493 internal static extern bool OpenProcessToken(IntPtr processHandle, uint desiredAccess, out IntPtr tokenHandle);494 495 /// <summary>496 /// Required to enable or disable the privileges in an access token.497 /// </summary>498 internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;499 500 /// <summary>501 /// Required to query an access token.502 /// </summary>503 internal const int TOKEN_QUERY = 0x00000008;504 505 /// <summary>506 /// Combines all possible access rights for a token.507 /// </summary>508 internal const int TOKEN_ALL_ACCESS = 0x001f01ff;509 510 internal const uint SE_PRIVILEGE_DISABLED = 0x00000000;511 internal const uint SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001;512 internal const uint SE_PRIVILEGE_ENABLED = 0x00000002;513 internal const uint SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000;514 515 internal const int ERROR_SUCCESS = 0x0;516 517 #region CreateProcess for SSH Remoting518 519#if !UNIX520 521 // Fields522 internal static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);523 internal static readonly UInt32 GENERIC_READ = 0x80000000;524 internal static readonly UInt32 GENERIC_WRITE = 0x40000000;525 internal static readonly UInt32 FILE_ATTRIBUTE_NORMAL = 0x80000000;526 internal static readonly UInt32 CREATE_ALWAYS = 2;527 internal static readonly UInt32 FILE_SHARE_WRITE = 0x00000002;528 internal static readonly UInt32 FILE_SHARE_READ = 0x00000001;529 internal static readonly UInt32 OF_READWRITE = 0x00000002;530 internal static readonly UInt32 OPEN_EXISTING = 3;531 532 [StructLayout(LayoutKind.Sequential)]533 internal sealed class PROCESS_INFORMATION534 {535 public IntPtr hProcess;536 public IntPtr hThread;537 public int dwProcessId;538 public int dwThreadId;539 540 public PROCESS_INFORMATION()541 {542 this.hProcess = IntPtr.Zero;543 this.hThread = IntPtr.Zero;544 }545 546 /// <summary>547 /// Dispose.548 /// </summary>549 public void Dispose()550 {551 Dispose(true);552 }553 554 /// <summary>555 /// Dispose.556 /// </summary>557 /// <param name="disposing"></param>558 private void Dispose(bool disposing)559 {560 if (disposing)561 {562 if (this.hProcess != IntPtr.Zero)563 {564 CloseHandle(this.hProcess);565 this.hProcess = IntPtr.Zero;566 }567 568 if (this.hThread != IntPtr.Zero)569 {570 CloseHandle(this.hThread);571 this.hThread = IntPtr.Zero;572 }573 }574 }575 }576 577 [StructLayout(LayoutKind.Sequential)]578 internal sealed class STARTUPINFO579 {580 public int cb;581 public IntPtr lpReserved;582 public IntPtr lpDesktop;583 public IntPtr lpTitle;584 public int dwX;585 public int dwY;586 public int dwXSize;587 public int dwYSize;588 public int dwXCountChars;589 public int dwYCountChars;590 public int dwFillAttribute;591 public int dwFlags;592 public short wShowWindow;593 public short cbReserved2;594 public IntPtr lpReserved2;595 public SafeFileHandle hStdInput;596 public SafeFileHandle hStdOutput;597 public SafeFileHandle hStdError;598 599 public STARTUPINFO()600 {601 this.lpReserved = IntPtr.Zero;602 this.lpDesktop = IntPtr.Zero;603 this.lpTitle = IntPtr.Zero;604 this.lpReserved2 = IntPtr.Zero;605 this.hStdInput = new SafeFileHandle(IntPtr.Zero, false);606 this.hStdOutput = new SafeFileHandle(IntPtr.Zero, false);607 this.hStdError = new SafeFileHandle(IntPtr.Zero, false);608 this.cb = Marshal.SizeOf(this);609 }610 611 public void Dispose(bool disposing)612 {613 if (disposing)614 {615 if ((this.hStdInput != null) && !this.hStdInput.IsInvalid)616 {617 this.hStdInput.Dispose();618 this.hStdInput = null;619 }620 621 if ((this.hStdOutput != null) && !this.hStdOutput.IsInvalid)622 {623 this.hStdOutput.Dispose();624 this.hStdOutput = null;625 }626 627 if ((this.hStdError != null) && !this.hStdError.IsInvalid)628 {629 this.hStdError.Dispose();630 this.hStdError = null;631 }632 }633 }634 635 public void Dispose()636 {637 Dispose(true);638 }639 }640 641 [StructLayout(LayoutKind.Sequential)]642 internal sealed class SECURITY_ATTRIBUTES643 {644 public int nLength;645 public SafeLocalMemHandle lpSecurityDescriptor;646 public bool bInheritHandle;647 648 public SECURITY_ATTRIBUTES()649 {650 this.nLength = 12;651 this.bInheritHandle = true;652 this.lpSecurityDescriptor = new SafeLocalMemHandle(IntPtr.Zero, true);653 }654 }655 656 [DllImport(PinvokeDllNames.CreateProcessDllName, CharSet = CharSet.Unicode, SetLastError = true)]657 [return: MarshalAs(UnmanagedType.Bool)]658 internal static extern bool CreateProcess(659 [MarshalAs(UnmanagedType.LPWStr)] string lpApplicationName,660 [MarshalAs(UnmanagedType.LPWStr)] string lpCommandLine,661 SECURITY_ATTRIBUTES lpProcessAttributes,662 SECURITY_ATTRIBUTES lpThreadAttributes,663 bool bInheritHandles,664 int dwCreationFlags,665 IntPtr lpEnvironment,666 [MarshalAs(UnmanagedType.LPWStr)] string lpCurrentDirectory,667 STARTUPINFO lpStartupInfo,668 PROCESS_INFORMATION lpProcessInformation);669 670 [DllImport(PinvokeDllNames.ResumeThreadDllName, CharSet = CharSet.Unicode, SetLastError = true)]671 public static extern uint ResumeThread(IntPtr threadHandle);672 673 internal static readonly uint RESUME_THREAD_FAILED = System.UInt32.MaxValue; // (DWORD)-1674 675#endif676 677 #endregion678 }679}680 