AppContainerUtils.zip/TestSharedMemory1/TestSharedMemory/TestSharedMemory.cpp
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <boost/shared_ptr.hpp>
#include <boost/filesystem.hpp>
#include <boost/foreach.hpp>
#include <Windows.h>
#include <Userenv.h>
#include "SharedStruct.h"
#pragma comment(lib, "Userenv.lib")
typedef boost::shared_ptr<boost::remove_pointer<PSID>::type> SHARED_SID;
void MyFreeSid(PSID sid) {
if (sid != NULL) {
::FreeSid(sid);
}
}
SHARED_SID ToSharedSID(PSID sid) {
return SHARED_SID(sid, &MyFreeSid);
}
typedef boost::shared_ptr<boost::remove_pointer<HANDLE>::type> SHARED_HANDLE;
void MyCloseHandle(const HANDLE handle) {
if (handle != NULL) {
::CloseHandle(handle);
}
}
void MyDeleteProcThreadAttributeList(const LPPROC_THREAD_ATTRIBUTE_LIST attrList) {
if (attrList != NULL) {
::DeleteProcThreadAttributeList(attrList);
}
}
class DeleteAppContainer {
public:
DeleteAppContainer(const wchar_t * const name) : name(name) { }
~DeleteAppContainer() {
::DeleteAppContainerProfile(name);
}
private:
const wchar_t * const name;
};
bool RunImpl(SHARED_HANDLE &processHandle, const SHARED_SID sid, const boost::filesystem::path &path, const HANDLE arg) {
const unsigned int attrCount = 3;
SIZE_T size;
::InitializeProcThreadAttributeList(NULL, attrCount, 0, &size);
typedef boost::shared_ptr<boost::remove_pointer<LPPROC_THREAD_ATTRIBUTE_LIST>::type> SHARED_ATTR_LIST;
const SHARED_ATTR_LIST attrList(reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(new unsigned char[size]), &MyDeleteProcThreadAttributeList);
if (::InitializeProcThreadAttributeList(attrList.get(), attrCount, 0, &size) == FALSE) {
return false;
}
SECURITY_CAPABILITIES sc;
sc.AppContainerSid = sid.get();
sc.Capabilities = NULL;
sc.CapabilityCount = 0;
sc.Reserved = 0;
if (::UpdateProcThreadAttribute(attrList.get(), 0, PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES, &sc, sizeof(sc), NULL, NULL) == FALSE) {
return false;
}
STARTUPINFOEXW startupInfoEx = { 0 };
startupInfoEx.StartupInfo.cb = sizeof(STARTUPINFOEXW); // StartupInfoのサイズではなくstartupInfoExのサイズである点に注意
startupInfoEx.lpAttributeList = attrList.get();
PROCESS_INFORMATION pi = { 0 };
// ハンドルをコマンドライン引数で渡す
std::wostringstream woss;
woss << path.wstring() << L" " << reinterpret_cast<unsigned int>(arg);
wchar_t buf[1024];
::wcscpy_s(buf, woss.str().c_str());
// bInheritHandles = TRUEでハンドルを継承させる
if (::CreateProcessW(path.wstring().c_str(), buf, NULL, NULL, TRUE, EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, reinterpret_cast<LPSTARTUPINFO>(&startupInfoEx), &pi) == FALSE) {
return false;
}
processHandle.reset(pi.hProcess, &MyCloseHandle);
::CloseHandle(pi.hThread);
return true;
}
bool Run(SHARED_HANDLE &processHandle, const wchar_t * const appContainerName, const boost::filesystem::path &path, const HANDLE arg) {
PSID sidImpl;
if (FAILED(::CreateAppContainerProfile(appContainerName, appContainerName, appContainerName, NULL, 0, &sidImpl))) {
return false;
}
DeleteAppContainer deleteAppContainer(appContainerName);
const SHARED_SID sid = ToSharedSID(sidImpl);
if (!RunImpl(processHandle, sid, path, arg)) {
return false;
}
return true;
}
SHARED_SID GetAppContainerSid(const wchar_t * const name) {
PSID sidImpl;
if (FAILED(::DeriveAppContainerSidFromAppContainerName(name, &sidImpl))) {
return SHARED_SID();
}
return ToSharedSID(sidImpl);
}
bool RunExist(SHARED_HANDLE &processHandle, const wchar_t * const appContainerName, const boost::filesystem::path &path, const HANDLE arg) {
const SHARED_SID sid = GetAppContainerSid(appContainerName);
if (!sid) {
return false;
}
if (!RunImpl(processHandle, sid, path, arg)) {
return false;
}
return true;
}
bool GetSharedMemoryPtr(void *&ptr, const HANDLE handle) {
ptr = ::MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (ptr == NULL) {
return false;
}
return true;
}
bool CreateSharedMemory(HANDLE &handle, const wchar_t * const sharedMemoryName, const unsigned int sharedMemorySize) {
// bInheritHandle = TRUEにすることでハンドルを継承可能にする
SECURITY_ATTRIBUTES attr = {0};
attr.nLength = sizeof(attr);
attr.bInheritHandle = TRUE;
attr.lpSecurityDescriptor = NULL;
handle = ::CreateFileMappingW(INVALID_HANDLE_VALUE, &attr, PAGE_READWRITE, 0, sharedMemorySize, sharedMemoryName);
if (handle == NULL) {
return false;
}
return true;
}
int main(const unsigned int argc, const char * const * const argv) {
std::locale::global(std::locale("japanese"));
if (argc != 2) {
std::wcout << L"usage: TestSharedMemory.exe exe_path" << std::endl;
std::wcin.ignore();
return 1;
}
const boost::filesystem::path path(argv[1]);
if (!boost::filesystem::is_regular_file(path)) {
std::wcout << L"Error: ファイルが見つかりませんでした" << std::endl;
std::wcin.ignore();
return 1;
}
const wchar_t * const appContainerName = L"AppConteinerTest";
const wchar_t * const sharedMemoryName = L"AppConteinerTestMemory";
HANDLE handle;
if (!CreateSharedMemory(handle, sharedMemoryName, sizeof(SharedStruct))) {
std::wcout << L"Error: 共有メモリーの生成に失敗しました" << std::endl;
std::wcin.ignore();
return 1;
}
void *ptr;
if (!GetSharedMemoryPtr(ptr, handle)) {
std::wcout << L"Error: 共有メモリーの取得に失敗しました" << std::endl;
std::wcin.ignore();
return 1;
}
SHARED_HANDLE processHandle;
if (!Run(processHandle, appContainerName, path, handle)) {
if (!RunExist(processHandle, appContainerName, path, handle)) {
std::wcout << L"Error: アプリの起動に失敗しました" << std::endl;
std::wcin.ignore();
return 1;
}
}
SharedStruct &sharedStruct = *reinterpret_cast<SharedStruct *>(ptr);
while (::WaitForSingleObject(processHandle.get(), 100) == WAIT_TIMEOUT) {
if (sharedStruct.changeFlag) {
sharedStruct.changeFlag = false;
std::wcout << sharedStruct.value << std::endl;
}
}
return 0;
}