void createProcessTracer_OnFunctionExited(
            DkmStackWalkFrame frame,
            StackFrameAnalyzer frameAnalyzer)
        {
            try {
            ulong processInfoAddr = Convert.ToUInt64(
            frameAnalyzer.GetArgumentValue(frame, "lpProcessInformation"));

            // Check the return address first, it should be in EAX.  CreateProcessAsUser and
            // CreateProcess both return 0 on failure.  If the function failed, there is no child to
            // attach to.
            if (0 == frame.VscxGetRegisterValue32(CpuRegister.Eax))
              return;

            // The process was successfully created.  Extract the PID from the PROCESS_INFORMATION
            // output param.  An attachment request must happend through the EnvDTE, which can only
            // be accessed from the VsPackage, so a request must be sent via a component message.
            DkmProcess process = frame.Process;
            int size = Marshal.SizeOf(typeof(PROCESS_INFORMATION));
            byte[] buffer = new byte[size];
            process.ReadMemory(processInfoAddr, DkmReadMemoryFlags.None, buffer);
            PROCESS_INFORMATION info = MarshalUtility.ByteArrayToStructure<PROCESS_INFORMATION>(buffer);
            DkmCustomMessage attachRequest = DkmCustomMessage.Create(
            process.Connection,
            process,
            PackageServices.VsPackageMessageGuid,
            (int)VsPackageMessage.AttachToChild,
            process.LivePart.Id,
            info.dwProcessId);
            attachRequest.SendToVsService(PackageServices.DkmComponentEventHandler, false);
              } catch (Exception exception) {
            Logger.LogException(
            exception,
            "An error occured handling the exit breakpoint.  HR = 0x{0:X}",
            exception.HResult);
              }
        }
 void createProcessTracer_OnFunctionEntered(
     DkmStackWalkFrame frame,
     StackFrameAnalyzer functionAnalyzer,
     out bool suppressExitBreakpoint)
 {
     // If this was not created with CREATE_SUSPENDED, then we can't automatically attach to this
       // child process.
       // TODO(zturner): OR in CREATE_SUSPENDED using WriteProcessMemory, then when the exit bp
       // hits, check if we OR'ed in CREATE_SUSPENDED, and if so, resume the process after the
       // attach.
       ProcessCreationFlags flags = (ProcessCreationFlags)
       Convert.ToUInt32(functionAnalyzer.GetArgumentValue(frame, "dwCreationFlags"));
       suppressExitBreakpoint = !flags.HasFlag(ProcessCreationFlags.CREATE_SUSPENDED);
 }