title: Minifilter PsSetCreateProcessNotifyRoutineEx gives BSOD only on certain computers "unexpected kernel mode trap"
body: <p>I am working on a simple process filtering minifilter driver.
  Managed to make it work in test mode, also managed to get it signed by Microsoft.
  Problem is: built it in release mode with the linker's /INTEGRITYCHECK option, signed it, works perfect on my machine, and on the virtual machines that i have hosted on my local machine for testing (hyper-V).</p>
  <p>As soon as I asked my colleague to run it, he gets a BSOD with &quot;UNEXPECTED KERNEL MODE TRAP&quot; after just opening some processes.</p>
  <p>I am attaching myself to PsSetCreateProcessNotifyRoutineEx, code below. Not sure where to look at this point, I fail to understand why can't I reproduce the issue.</p>
  <p>Registering with this:</p>
  <pre><code>KdPrint((DRIVER_PREFIX &quot;Registering process callback\n&quot;));
          //PROCESS CALLBACKS
          status = PsSetCreateProcessNotifyRoutineEx(OnProcessNotify, FALSE);
          if (!NT_SUCCESS(status)) {
              KdPrint((DRIVER_PREFIX &quot;failed to register process callback (0x%08X)\n&quot;, status));
              KdPrint((DRIVER_PREFIX &quot;Unregistering OnProcessNotify... \r\n&quot;));
              PsSetCreateProcessNotifyRoutineEx(OnProcessNotify, TRUE);
              KdPrint((DRIVER_PREFIX &quot;Unregistered OnProcessNotify \r\n&quot;));
              return status;
          }
  </code></pre>
  <p>The structure that I'm sending to the clients:</p>
  <pre><code>typedef struct _ACCESS_DATA
  {
      UINT32  ProcessID;
      UINT32  EventType;
      WCHAR   Path[MAX_PATH]; // [260 bytes] Max size of a full path in windows.
      WCHAR   CommandLine[MAX_CMDLINE]; // [8191 bytes] Max size of a commandline
  } ACCESS_DATA, * PACCESS_DATA;
  </code></pre>
  <p>The reply structure that I'm waiting from the clients:</p>
  <pre><code>typedef struct _REPLY_DATA
  {
      BOOLEAN Allow;      // TRUE if request is permitted, FALSE if not permitted.
      UINT32  Reserved;   // Alignment. Must be NULL.
  } REPLY_DATA, * PREPLY_DATA;
  </code></pre>
  <p>The main method that I'm using. Basically upon any process interception, I am asking the client apps whether I should allow it or not.
  I have two separate communication channel to ask two separate applications.
  Again, this works perfectly on my computer and on any virtual machine I create on my computer. Not on two of my colleagues machines, nor on some other virtual machines hosted on a different on-prem server. Can't figure out why. All of them are Windows 10 x64, the driver was built for Windows 10 x64.</p>
  <pre><code>void OnProcessNotify(_Inout_ PEPROCESS Process, _In_ HANDLE ProcessId, _Inout_opt_ PPS_CREATE_NOTIFY_INFO CreateInfo) {
  
      UNREFERENCED_PARAMETER(Process);
  
      KdPrint((DRIVER_PREFIX &quot;Started something \r\n&quot;));
      if (CreateInfo) {
  
          if (CreateInfo-&gt;FileOpenNameAvailable &amp;&amp; CreateInfo-&gt;ImageFileName)
          {
              //KdPrint((&quot;Pid: %p\n&quot;, ProcessId));
              KdPrint((DRIVER_PREFIX &quot;ImageFilePath: %wZ\r\n&quot;, CreateInfo-&gt;ImageFileName));
              KdPrint((DRIVER_PREFIX &quot;CmdLine: %wZ\r\n&quot;, CreateInfo-&gt;CommandLine));
  
              PREPLY_DATA pReplyData = NULL;
              PREPLY_DATA ac_pReplyData = NULL;
              PAGED_CODE();
  
              pReplyData = ExAllocatePoolWithTag(NonPagedPool, sizeof(REPLY_DATA), REPLY_DATA_TAG);
              ac_pReplyData = ExAllocatePoolWithTag(NonPagedPool, sizeof(REPLY_DATA), REPLY_DATA_TAG);
              if (pReplyData != NULL &amp;&amp; ac_pReplyData != NULL) {
                  PPROCESS_ACCESS_DATA pAccessData;
                  pAccessData = ExAllocatePoolWithTag(NonPagedPool, sizeof(PROCESS_ACCESS_DATA), ACCESS_DATA_TAG);
                  if (pAccessData != NULL) {
                      //do work
                      pAccessData-&gt;ProcessID = (UINT32)HandleToPid(ProcessId);
                      //(UINT32)(((ULONG_PTR)ProcessId) &amp; 0xFFFFFFFF);
                      pAccessData-&gt;EventType = 8;
                      pAccessData-&gt;ParentProcessID = (UINT32)HandleToPid(CreateInfo-&gt;ParentProcessId);
  
                      WCHAR ProcessPath[MAX_PATH] = { 0 };
                      RtlCopyMemory(ProcessPath, CreateInfo-&gt;ImageFileName-&gt;Buffer, CreateInfo-&gt;ImageFileName-&gt;MaximumLength);
                      
                      RtlZeroMemory(pAccessData-&gt;Path, MAX_PATH * sizeof(wchar_t));
                      //RtlCopyMemory(pAccessData-&gt;Path, FileNameInfo-&gt;Name.Buffer, FileNameInfo-&gt;Name.Length);
                      RtlCopyMemory(pAccessData-&gt;Path, ProcessPath, MAX_PATH * sizeof(wchar_t));
  
                      WCHAR CommandLine[MAX_CMDLINE] = { 0 };
                      RtlCopyMemory(CommandLine, CreateInfo-&gt;CommandLine-&gt;Buffer, CreateInfo-&gt;CommandLine-&gt;MaximumLength);
  
                      RtlZeroMemory(pAccessData-&gt;CommandLine, MAX_CMDLINE * sizeof(wchar_t));
                      //RtlCopyMemory(pAccessData-&gt;CommandLine, FileNameInfo-&gt;Name.Buffer, FileNameInfo-&gt;Name.Length);
                      RtlCopyMemory(pAccessData-&gt;CommandLine, CommandLine, MAX_CMDLINE * sizeof(wchar_t));
  
                      KdPrint((DRIVER_PREFIX &quot;File trying to Execute: %ws\r\n&quot;, CreateInfo-&gt;ImageFileName-&gt;Buffer));
  
                      //begin send the request to the first client app, if connected
                      LARGE_INTEGER Timeout;
                      Timeout.QuadPart = -((LONGLONG)1 * 1 * 1000 * 1000); // 1000 milliseconds
                      NTSTATUS status;
                      ULONG ReplyDataSize = sizeof(REPLY_DATA);
                      status = FltSendMessage(FilterHandle, &amp;IN_ProcessPort, pAccessData, sizeof(PROCESS_ACCESS_DATA), pReplyData, &amp;ReplyDataSize, &amp;Timeout);
                      if (Timeout.QuadPart != 0 &amp;&amp; NT_SUCCESS(status))
                      {
                          //block or not block
                          if (pReplyData-&gt;Allow == TRUE)
                          {
                              KdPrint((DRIVER_PREFIX &quot;File Allowed to Execute: %ws\r\n&quot;, CreateInfo-&gt;ImageFileName-&gt;Buffer));
                          }
                          else
                          {
                              CreateInfo-&gt;CreationStatus = STATUS_ACCESS_DENIED;
                              KdPrint((DRIVER_PREFIX &quot;Process DENIED to Execute: %ws\r\n&quot;, CreateInfo-&gt;ImageFileName-&gt;Buffer));
                          }
                      }
                      //end send the request to the first client app, if connected
  
                      //begin send the request to the second client app, if connected
                      LARGE_INTEGER AC_Timeout;
                      AC_Timeout.QuadPart = -((LONGLONG)10 * 1000 * (1000 * 10) /*nanoseconds*/); // 10 seconds
                      NTSTATUS ac_status;
                      ULONG AC_ReplyDataSize = sizeof(REPLY_DATA);
                      ac_status = FltSendMessage(FilterHandle, &amp;AC_ProcessPort, pAccessData, sizeof(PROCESS_ACCESS_DATA), ac_pReplyData, &amp;AC_ReplyDataSize, &amp;AC_Timeout);
                      if (AC_Timeout.QuadPart != 0 &amp;&amp; NT_SUCCESS(ac_status))
                      {
                          //block or not block
                          if (ac_pReplyData-&gt;Allow == FALSE)
                          {
                              CreateInfo-&gt;CreationStatus = STATUS_ACCESS_DENIED;
                              KdPrint((DRIVER_PREFIX &quot;Process DENIED to Execute: %ws\r\n&quot;, CreateInfo-&gt;ImageFileName-&gt;Buffer));
                          }
                          else
                          {
                              KdPrint((DRIVER_PREFIX &quot;File Allowed to Execute: %ws\r\n&quot;, CreateInfo-&gt;ImageFileName-&gt;Buffer));
                          }
                      }
                      //end send the request to the first client app, if connected
  
                      
  
                      ExFreePoolWithTag(pAccessData, ACCESS_DATA_TAG);
                  }
                  ExFreePoolWithTag(pReplyData, REPLY_DATA_TAG);
                  ExFreePoolWithTag(ac_pReplyData, REPLY_DATA_TAG);
              }
          }
      }
  </code></pre>