Can Windows 8 Apps Share Memory?

August 21, 2012

Windows 8 Applications (formerly Metro) run inside a sandbox, making communicating with other application difficult at best. There is no easy way to do it, and for good reason, too. When one app is running, all other may be suspended, so what’s the point of communicating anyway? Furthermore, there is no guarantee that the other app even exists on the machine.

Still, suppose we wanted to share some information (I’m not talking about the standard share contract) via (say) shared memory. Can we achieve that?

Flipping to the documentation of the CreateFileMapping Win32 API shows that unfortunately this is only available for desktop apps. A new function exists, however, called CreateFileMappingFromApps that works only in Windows 8 apps. Great! Can we use that? Let’s try.

I’ve created two simple C++ Windows 8 Applications (Metro or Store apps) that have a simple UI consisting of a TextBox with two buttons, one for writing to the shared memory, the other for reading. The XAML looks something like this:

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">

    <Grid.RowDefinitions>

        <RowDefinition Height="Auto" />

        <RowDefinition />

        <RowDefinition Height="Auto" />

    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>

        <ColumnDefinition />

        <ColumnDefinition />

    </Grid.ColumnDefinitions>

    <TextBlock Grid.ColumnSpan="2" HorizontalAlignment="Center" FontSize="40" Text="Application 2" Margin="10"/>

    <TextBox Grid.Row="1" Margin="20" AcceptsReturn="True" BorderThickness="2" Grid.ColumnSpan="2" x:Name="_text" FontSize="20"/>

    <Button FontSize="40" Content="Write" HorizontalAlignment="Center" Grid.Row="2" Margin="10" Click="OnWrite"/>

    <Button FontSize="40" Content="Read" HorizontalAlignment="Center" Grid.Row="2" Margin="10" Grid.Column="1" Click="OnRead"/>

</Grid>

In the MainPage constructor, we can create the file mapping (section) object and save it in a member handler:

m_hMemFile = ::CreateFileMappingFromApp(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 1 << 20, L"MySharedMem");

This creates a 1MB shared memory section named “MySharedMem” backed up by the system paging file.

To write some text into that memory, we can use the following code:

void * p = ::MapViewOfFileFromApp(m_hMemFile, FILE_MAP_WRITE, 0, 0);

::wcscpy((WCHAR*)p, _text->Text->Data());

::UnmapViewOfFile(p);

MapViewOfFileFromApp is the equivalent of MapViewOfFile API that is forbidden in Windows 8 apps. _text is the name of the TextBox created in XAML. Reading can be similarly achieved:

void * p = ::MapViewOfFileFromApp(m_hMemFile, FILE_MAP_READ, 0, 0);

_text->Text = ref new String((PWSTR)p);

::UnmapViewOfFile(p);

Running a single application has the desired effect – the memory is written and read from correctly, which may not be surprising.

If two similar application are running, that use the same code, i.e. – the same file mapping object name – sharing is possible.

However, trying this simply fails. The handles are created successfully, the writing and reading succeed as well. So, what’s wrong?

Opening Process Explorer reveals the unpleasant truth. Here’s the handle view for the first app, concentrating on the section object in question:

SNAGHTMLbcf1dda

It seems that the name of the section is not really MySharedMem, but something that consists of some SID-looking string. Running another application shows the following in Process Explorer:

SNAGHTMLbd10338

That’s a completely different name! That’s why the sharing wasn’t working.

Communicating between a desktop app and a Windows 8 app is problematic for exactly the same reason; desktop apps names are under the BasedNamedObjects logical directory (and not AppContainerNamedObjects).

One option that we can try is prefixing the object name with “Global\”, such as “Global\\MySharedMem”. This should create the object in session 0, allowing easy sharing. This, unfortunately, fails, because of a missing privilege that a Windows 8 app does not (and cannot) have.

The above is not specific to section objects, but to any kernel object created from a Windows 8 app process, such as a mutex, semaphore, file, etc. Another option we may consider is using the DuplicateHandle API, and although this is permitted, we first need a handle to the other process, which requires a call to OpenProcess, which, unfortunately cannot be used in Windows 8 apps.

So, there you have it. Windows 8 apps are really in a tight box.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

4 comments

  1. Lior TalAugust 21, 2012 ב 20:46

    What is your opinion of this design? Do you think a strict sandbox is a good or bad thing/

    Also, do u know if other platforms (for example iOS) are also very strict on sharing data between apps?

    Reply
  2. pavelyAugust 21, 2012 ב 23:44

    I believe it’s inevitable, as an app installed from the Store can’t be sure of anything except the existence of Windows. If it relied on some other app and that wasn’t available – the user would be unhappy. And user happiness is a prime concern, especially on tablet devices.
    As for other platforms – as far as I know (and I’m no expert), it’s similar in iOS.

    Reply
  3. Lior TalAugust 24, 2012 ב 22:57

    Relying on files or other app is one thing. But for example, take storage as an example.
    The metro IE10 browser is a Windows Store app, and as such stores downloaded stuff into its own designated (sandboxed) location. This means i can’t download some file and open it later on with some other app…

    Reply
  4. pavelyAugust 25, 2012 ב 17:13

    Not true…
    You can download something and place it in “My Documents” or similar, and other apps can access it (given they declare that capability).

    Reply