title: Exceptions constantly thrown when launching app with my custom WINAPI Debugger
body: <p>I'm in the process of experimenting with creating my own custom debugger with C++ in Visual Studio 2017. Testing a few console applications it is fine. However when I launch notepad with it, it is OK until I hit File -> Open dialog and it goes into constant loop with output these two exceptions code and the open dialog box doesn't open:</p>
  
  <pre><code>Exception: 3221356611
  Exception: 998
  </code></pre>
  
  <p>When same process was launched under WinDbg these exceptions didn't occur. 
  The code is compiled as x86 and launching 32-bit process on Windows 10 1803 build 17134.523 x64.</p>
  
  <p>Any suggestions on what might cause these?</p>
  
  <pre><code>#include "targetver.h"
  #include &lt;stdio.h&gt;
  #include &lt;tchar.h&gt;
  #include &lt;string&gt;
  #include &lt;iostream&gt;
  #include &lt;map&gt;
  
  std::map &lt; LPVOID, std::wstring &gt; DllNameMap;
  
  int main()
  {
      std::wstring filename(L"c:\\windows\\syswow64\\notepad.exe");
      STARTUPINFO si;
      PROCESS_INFORMATION pi;
  
      ZeroMemory(&amp;si, sizeof(si));
      si.cb = sizeof(si);
      ZeroMemory(&amp;pi, sizeof(pi));
  
      DEBUG_EVENT debugEvent;
  
      // Start the child process. 
      if (!CreateProcess(NULL,   // No module name (use command line)
          (LPWSTR)filename.c_str(),           // Command line
          NULL,               // Process handle not inheritable
          NULL,               // Thread handle not inheritable
          FALSE,              // Set handle inheritance to FALSE
          CREATE_SUSPENDED,   // No creation flags
          NULL,               // Use parent's environment block
          NULL,               // Use parent's starting directory 
          &amp;si,                // Pointer to STARTUPINFO structure
          &amp;pi)                // Pointer to PROCESS_INFORMATION structure
          )
      {
          printf("CreateProcess failed (%d).\n", GetLastError());
          return -1;
      }
  
      if (DebugActiveProcess(pi.dwProcessId))
      {
          ResumeThread(pi.hThread);
  
          std::cout &lt;&lt; "Debugger attached!" &lt;&lt; std::endl;
          EnterDebugLoop(&amp;debugEvent,pi.hProcess);
      }
      return 0;
  }
  
  void EnterDebugLoop(const LPDEBUG_EVENT DebugEv,HANDLE hProcess)
  {
  
      DWORD dwContinueStatus = DBG_CONTINUE; // exception continuation 
  
      for (;;)
      {
          // Wait for a debugging event to occur. The second parameter indicates
          // that the function does not return until a debugging event occurs. 
  
          WaitForDebugEvent(DebugEv, INFINITE);
  
          // Process the debugging event code. 
  
          switch (DebugEv-&gt;dwDebugEventCode)
          {
          case EXCEPTION_DEBUG_EVENT:
              // Process the exception code. When handling 
              // exceptions, remember to set the continuation 
              // status parameter (dwContinueStatus). This value 
              // is used by the ContinueDebugEvent function. 
  
              std::cout &lt;&lt; "Exception: " &lt;&lt; DebugEv-&gt;u.Exception.ExceptionRecord.ExceptionCode &lt;&lt; std::endl;
  
              switch (DebugEv-&gt;u.Exception.ExceptionRecord.ExceptionCode)
              {
              case EXCEPTION_ACCESS_VIOLATION:
                  std::cout &lt;&lt; "ACCESS VIOLATION" &lt;&lt; std::endl;
                  // First chance: Pass this on to the system. 
                  // Last chance: Display an appropriate error. 
                  break;
  
              case EXCEPTION_BREAKPOINT:
  
                  std::cout &lt;&lt; "BREAKPOINT" &lt;&lt; std::endl;
                  // First chance: Display the current 
                  // instruction and register values. 
                  break;
  
              case EXCEPTION_DATATYPE_MISALIGNMENT:
                  std::cout &lt;&lt; "DATATYPE MISALIGNMENT" &lt;&lt; std::endl;
                  // First chance: Pass this on to the system. 
                  // Last chance: Display an appropriate error. 
                  break;
  
              case EXCEPTION_SINGLE_STEP:
                  std::cout &lt;&lt; "SINGLE STEP" &lt;&lt; std::endl;
                  // First chance: Update the display of the 
                  // current instruction and register values. 
                  break;
  
              case DBG_CONTROL_C:
                  std::cout &lt;&lt; "CTRL+C" &lt;&lt; std::endl;
                  // First chance: Pass this on to the system. 
                  // Last chance: Display an appropriate error. 
                  break;
  
              default:
                      // Handle other exceptions. 
                  break;
              }
  
              break;
  
          case CREATE_THREAD_DEBUG_EVENT:
              std::cout &lt;&lt; "Create Thread" &lt;&lt; std::endl;
              // As needed, examine or change the thread's registers 
              // with the GetThreadContext and SetThreadContext functions; 
              // and suspend and resume thread execution with the 
              // SuspendThread and ResumeThread functions. 
              break;
  
          case CREATE_PROCESS_DEBUG_EVENT:
              std::cout &lt;&lt; "Create Process" &lt;&lt; std::endl;
              // As needed, examine or change the registers of the
              // process's initial thread with the GetThreadContext and
              // SetThreadContext functions; read from and write to the
              // process's virtual memory with the ReadProcessMemory and
              // WriteProcessMemory functions; and suspend and resume
              // thread execution with the SuspendThread and ResumeThread
              // functions. Be sure to close the handle to the process image
              // file with CloseHandle.
  
              //dwContinueStatus = OnCreateProcessDebugEvent(DebugEv);
              break;
  
          case EXIT_THREAD_DEBUG_EVENT:
              // Display the thread's exit code. 
              std::cout &lt;&lt; "Exit Thread Exit Code " &lt;&lt; DebugEv-&gt;u.ExitThread.dwExitCode &lt;&lt; std::endl;
  
  
              //dwContinueStatus = OnExitThreadDebugEvent(DebugEv);
              break;
  
          case EXIT_PROCESS_DEBUG_EVENT:
              // Display the process's exit code. 
              std::cout &lt;&lt; "Exit process Exit Code " &lt;&lt; DebugEv-&gt;u.ExitProcess.dwExitCode &lt;&lt; std::endl;
              ///dwContinueStatus = OnExitProcessDebugEvent(DebugEv);
              break;
  
          case LOAD_DLL_DEBUG_EVENT:
          {
              PVOID pDllPath = NULL;
              PUCHAR DllPath[(MAX_PATH + 1) * sizeof(WCHAR)];
              DWORD dwLen = 0;
              ZeroMemory(DllPath, sizeof(DllPath));
  
              if (DebugEv-&gt;u.LoadDll.lpImageName == NULL)
              {
                  break;
              }
  
              // read DLL name pointer value
              if (ReadProcessMemory(
                  hProcess,
                  DebugEv-&gt;u.LoadDll.lpImageName,
                  &amp;pDllPath, sizeof(PVOID),
                  &amp;dwLen) &amp;&amp; pDllPath)
              {
                  dwLen = (DebugEv-&gt;u.LoadDll.fUnicode ? MAX_PATH * sizeof(WCHAR) : MAX_PATH);
  
                  // read DLL name
                  if (ReadProcessMemory(
                      hProcess,
                      pDllPath,
                      DllPath, dwLen,
                      &amp;dwLen))
                  {
                      char szDllPath[MAX_PATH], *lpszDllName = NULL;
  
                      if (DebugEv-&gt;u.LoadDll.fUnicode)
                      {
                          std::wstring path((wchar_t*)DllPath);
                          DllNameMap.insert(std::make_pair(DebugEv-&gt;u.LoadDll.lpBaseOfDll, path));
                          std::wcout &lt;&lt; "Image loaded (Unicode): " &lt;&lt; path.c_str() &lt;&lt; std::endl;
                      }
                      else
                      {
                          // todo: Add to DllNameMAp
                          std::wcout &lt;&lt; "Image loaded: " &lt;&lt; DllPath &lt;&lt; std::endl;
  
                      }
                  }
                  else
                  {
                      std::cout &lt;&lt; "Error processing memory : " &lt;&lt; GetLastError() &lt;&lt; std::endl;
                  }
              }
              else
              {
                  std::wcout &lt;&lt; "ERROR reading process memory : " &lt;&lt; GetLastError() &lt;&lt; std::endl;
              }
          }
              // Read the debugging information included in the newly 
              // loaded DLL. Be sure to close the handle to the loaded DLL 
              // with CloseHandle.
  
              ///dwContinueStatus = OnLoadDllDebugEvent(DebugEv);
              break;
  
          case UNLOAD_DLL_DEBUG_EVENT:
              std::wcout &lt;&lt; "Unload DLL: " &lt;&lt; DllNameMap[DebugEv-&gt;u.UnloadDll.lpBaseOfDll] &lt;&lt; std::endl;
              break;
  
          case OUTPUT_DEBUG_STRING_EVENT:
              // Display the output debugging string. 
              std::wcout &lt;&lt; "Debug Event" &lt;&lt; std::endl;
              if (DebugEv-&gt;u.DebugString.fUnicode)
              {
                  std::wcout &lt;&lt; (wchar_t)DebugEv-&gt;u.DebugString.lpDebugStringData &lt;&lt; std::endl;
              }
  
              //dwContinueStatus = OnOutputDebugStringEvent(DebugEv);
              break;
  
          case RIP_EVENT:
              //dwContinueStatus = OnRipEvent(DebugEv);
              break;
          }
  
          // Resume executing the thread that reported the debugging event. 
  
          ContinueDebugEvent(DebugEv-&gt;dwProcessId,
              DebugEv-&gt;dwThreadId,
              dwContinueStatus);
      }
  }
  </code></pre>