I am trying to set up a shared 2D texture between an uwp application and a win32 application. The minimal reproducible example uses the CoreApp project template (C++/WinRT), in which all functions from the App class (except the Run method) are empty (the Run method remains unchanged). Inside wWinMain, creation of shared texture and starting app occurs.
int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
// Create D3D11 Device and Context
ID3D11Device1* d3d11Device;
ID3D11DeviceContext1* d3d11DeviceContext;
{
ID3D11Device* baseDevice;
ID3D11DeviceContext* baseDeviceContext;
D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_1 };
UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
D3D11CreateDevice(
0,
D3D_DRIVER_TYPE_HARDWARE,
0,
creationFlags,
featureLevels,
ARRAYSIZE(featureLevels),
D3D11_SDK_VERSION,
&baseDevice,
0,
&baseDeviceContext);
baseDevice->QueryInterface(__uuidof(ID3D11Device1), (void**)&d3d11Device);
baseDevice->Release();
baseDeviceContext->QueryInterface(__uuidof(ID3D11DeviceContext1), (void**)&d3d11DeviceContext);
baseDeviceContext->Release();
}
HRESULT result;
D3D11_TEXTURE2D_DESC texDesc;
texDesc.Width = 360;
texDesc.Height = 360;
texDesc.MipLevels = 1;
texDesc.ArraySize = 1;
texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Usage = D3D11_USAGE_DEFAULT;
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_RENDER_TARGET;
texDesc.CPUAccessFlags = 0;
texDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_NTHANDLE | D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
result = d3d11Device->CreateTexture2D(&texDesc, nullptr, &texture2D);
IDXGIResource1* pResource;
texture2D->QueryInterface(__uuidof(IDXGIResource1), (void**)&pResource);
result = pResource->CreateSharedHandle(
nullptr,
DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
L"SharedTexture2D",
&textureHandle);
CoreApplication::Run(make<App>());
}
Win32 app is based on empty project with added main.cpp file.
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <string>
#include <Userenv.h>
#include <windows.h>
#include <d3d11_1.h>
#include <windows.h>
#include <d3d11_1.h>
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "Userenv.lib")
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int /*nShowCmd*/)
{
// Create D3D11 Device and Context as for uwp
// Try to open shared resource by name
// from Package.appmanifest of uwp project
constexpr auto packageFamilyName= L"b0660272-d6e8-493b-8da6-7e324d3652f3_6jxptbrcxhds4";
PSID psid{};
DeriveAppContainerSidFromAppContainerName(packageFamilyName, &psid);
auto path = std::wstring();
path.resize(256u);
ULONG returnedPathSize = 0u;
auto status = GetAppContainerNamedObjectPath(
nullptr,
psid,
path.size(),
(LPWSTR)(path.data()),
&returnedPathSize);
path.insert(returnedPathSize - 1u, L"\\SharedTexture2D");
ID3D11Texture2D* texture;
auto result = d3d11Device->OpenSharedResourceByName(
path.c_str(),
DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
__uuidof(ID3D11Texture2D),
(void**)&texture);
return result;
}
UWP creates the shared handle and returns S_OK. Then, I try to open the resource from the win32 app and there is E_INVALIDARG One or more arguments are invalid error code.
When, I have two win32 apps, the solution above works. What is the problem and how can I deal with it?
I guess it is related to the UWP sandbox and maybe there is a need to set some security attributes or modify the name of the shared resource, but I cannot find any information.
Thanks in advance!
Update:
As suggested by user Chuck Walbourn, I modified the code by adding DeriveAppContainerSidFromAppContainerName.
A more precise description to easier reproduce of problem.
As suggested by user @Simon Mourier - I have changed the package family to the package family name as argument of DeriveAppContainerSidFromAppContainerName and it works now :)
The issue is that SharedTexture2D is not a fully qualified object name, so it doesn't exist when you use it from the Win32 application.
I believe you need to use GetAppContainerNamedObjectPath from the Win32 app.
There are some specific instructions on how to get a shared handle to have the right permissions to be visible to a particular UWP SI. See Microsoft Learn. You may be able to get it to work by providing a non-null
SECURITY_ATTRIBUTES
, but this is mostly an issue for UWPs trying to open handles created by Win32 apps which is the opposite of your scenario.