title: Accessing the number of shared memory mapped file views (Windows)
body: <p>I am developing a multi-platform C++ application (mainly Windows and Linux), now I face the need to be able to limit the maximum number of instances of the application that may run at the same time (in the same machine).</p>
  
  <p>I have already a shared memory module that uses:</p>
  
  <ul>
  <li>Linux: System V shared memory (shmget(), shmat()...)</li>
  <li>Windows: Memory mapped files (CreateFileMapping(), OpenFileMapping(), MapViewOfFile(),...)</li>
  </ul>
  
  <p>In linux I can easily control the number of instances running with this kind of code:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;sys/shm.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;stdlib.h&gt;
  
  int main(void)
  {
      struct shmid_ds shm;
      int shmId;
      key_t shmKey = 123456; // A unique key...
  
      // Allocating 1 byte shared memory segment
      // open it if already existent and rw user permission
      shmId = shmget(shmKey, 1, IPC_CREAT|0x0180);
  
      // Attach to the shared memory segment
      shmat(shmId, (char *) 0, SHM_RDONLY);
  
      // Get the number of attached "clients"
      shmctl(shmId, IPC_STAT, &amp;shm);
  
      // Check limit
      if (shm.shm_nattch &gt; 4) {
          printf("Limit exceeded: %ld &gt; 4\n", shm.shm_nattch);
          exit(1);
      }
  
      //...
      sleep(30);
  }
  </code></pre>
  
  <p>The nice thing of this code is that when the application is killed or crashes the system takes care decrementing the number of attached clients.</p>
  
  <p>Now my question is, <strong>how to implement this in Windows?</strong> (using memory mapped files). The <em>"same"</em> code translated to Windows memory mapped files would be (more or less):</p>
  
  <pre><code>void functionName(void)
  {
      // Create the memory mapped file (in system pagefile)
      HANDLE hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE|SEC_COMMIT,
                    0, 1, "Global\\UniqueShareName");
  
      // Map the previous memory mapped file into the address space
      char *addr = (char*)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
  
      // How can I check now the number of views mapped?
  }
  </code></pre>
  
  <p>I have been searching for quite some time and I cannot find how to get <strong>the number of opened views</strong>.</p>
  
  <p>From the <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa366761(v=vs.85).aspx" rel="nofollow noreferrer">CreateFileMapping function</a>:</p>
  
  <blockquote>
    <p>Mapped views of a file mapping object maintain <strong>internal references</strong> to
    the object, and a file mapping object does not close until all
    references to it are released. Therefore, to fully close a file
    mapping object, an application must unmap all mapped views of the file
    mapping object by calling UnmapViewOfFile and close the file mapping
    object handle by calling CloseHandle. These functions can be called in
    any order.</p>
  </blockquote>
  
  <p>From <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa366882(v=vs.85).aspx" rel="nofollow noreferrer">UnmapViewOfFile function</a>:</p>
  
  <blockquote>
    <p>Unmapping a mapped view of a file invalidates the range occupied by
    the view in the address space of the process and makes the range
    available for other allocations. It removes the working set entry for
    each unmapped virtual page that was part of the working set of the
    process and reduces the working set size of the process. <strong>It also
    decrements the share count of the corresponding physical page</strong>.</p>
  </blockquote>
  
  <p>But I cannot get that <strong>shared count</strong>, and the only stackoverflow question regarding this matter (that I have found) is unanswered: <a href="https://stackoverflow.com/questions/41593517/number-of-mapped-views-to-a-shared-memory-on-windows">Number of mapped views to a shared memory on Windows</a></p>
  
  <p>I would really appreciate if anybody could help me with this.</p>
  
  <hr>
  
  <h2>Solution</h2>
  
  <p>(<strong>Note:</strong> Although may not be 100% reliable, see the comments section)</p>
  
  <p>From the comments of <a href="https://stackoverflow.com/users/6401656/rbmm">RbMm</a> and <a href="https://stackoverflow.com/users/205580/eryksun">eryksun</a> (Thanks!) I am able to solve the question with this code:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;windows.h&gt;
  #include &lt;winternl.h&gt;
  
  typedef NTSTATUS (__stdcall *NtQueryObjectFuncPointer) (
              HANDLE                   Handle,
              OBJECT_INFORMATION_CLASS ObjectInformationClass,
              PVOID                    ObjectInformation,
              ULONG                    ObjectInformationLength,
              PULONG                   ReturnLength);
  
  int main(void)
  {
      _PUBLIC_OBJECT_BASIC_INFORMATION pobi;
      ULONG rLen;
  
      // Create the memory mapped file (in system pagefile) (better in global namespace
      // but needs SeCreateGlobalPrivilege privilege)
      HANDLE hMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE|SEC_COMMIT,
                    0, 1, "Local\\UniqueShareName");
  
      // Get the NtQUeryObject function pointer and then the handle basic information
      NtQueryObjectFuncPointer _NtQueryObject = (NtQueryObjectFuncPointer)GetProcAddress(
              GetModuleHandle("ntdll.dll"), "NtQueryObject");
  
      _NtQueryObject(hMap, ObjectBasicInformation, (PVOID)&amp;pobi, (ULONG)sizeof(pobi), &amp;rLen);
  
      // Check limit
      if (pobi.HandleCount &gt; 4) {
          printf("Limit exceeded: %ld &gt; 4\n", pobi.HandleCount);
          exit(1);
      }
      //...
      Sleep(30000);
  }
  </code></pre>
  
  <p>But to be correct I should be using the Global kernel namespace, which needs a privilege (SeCreateGlobalPrivilege). So at the end I may resort to the named pipe solution (very nice and neat).</p>