1 // Copyright 2005-2019 The Mumble Developers. All rights reserved.
2 // Use of this source code is governed by a BSD-style license
3 // that can be found in the LICENSE file at the root of the
4 // Mumble source tree or at <https://www.mumble.info/LICENSE>.
5 
6 #include "mumble_pch.hpp"
7 
8 #include "SharedMemory.h"
9 
10 #ifndef _WIN32_WINNT
11 #define  _WIN32_WINNT 0x0501
12 #include <windows.h>
13 #endif
14 
15 #include <QtCore/QDebug>
16 
17 struct SharedMemory2Private {
18 	HANDLE hMemory;
19 };
20 
SharedMemory2(QObject * p,unsigned int minsize,const QString & memname)21 SharedMemory2::SharedMemory2(QObject *p, unsigned int minsize, const QString &memname) : QObject(p) {
22 	a_ucData = NULL;
23 
24 	d = new SharedMemory2Private();
25 	d->hMemory = NULL;
26 
27 	if (memname.isEmpty()) {
28 		// Create a new segment
29 
30 		for (int i=0;i<100;++i) {
31 			qsName = QString::fromLatin1("Local\\MumbleOverlayMemory%1").arg(++uiIndex);
32 			d->hMemory = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, minsize, qsName.toStdWString().c_str());
33 			if (d->hMemory && GetLastError() != ERROR_ALREADY_EXISTS) {
34 				break;
35 			}
36 
37 			if (d->hMemory)
38 				CloseHandle(d->hMemory);
39 			d->hMemory = NULL;
40 		}
41 	} else {
42 		// Open existing segment
43 
44 		qsName = memname;
45 		d->hMemory = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, minsize, qsName.toStdWString().c_str());
46 		qWarning("%p %lx", d->hMemory, GetLastError());
47 		if (GetLastError() != ERROR_ALREADY_EXISTS) {
48 			qWarning() << "SharedMemory2: Memory doesn't exist" << qsName;
49 			if (d->hMemory) {
50 				CloseHandle(d->hMemory);
51 				d->hMemory = NULL;
52 			}
53 		}
54 	}
55 
56 	if (d->hMemory == NULL) {
57 		qWarning() << "SharedMemory2: CreateFileMapping failed for" << qsName;
58 	} else {
59 		a_ucData = reinterpret_cast<unsigned char *>(MapViewOfFile(d->hMemory, FILE_MAP_ALL_ACCESS, 0, 0, 0));
60 
61 		if (a_ucData == NULL) {
62 			qWarning() << "SharedMemory2: Failed to map memory" << qsName;
63 		} else {
64 			MEMORY_BASIC_INFORMATION mbi;
65 			memset(&mbi, 0, sizeof(mbi));
66 			if ((VirtualQuery(a_ucData, &mbi, sizeof(mbi)) == 0) || (mbi.RegionSize < minsize)) {
67 				qWarning() << "SharedMemory2: Memory too small" << qsName << mbi.RegionSize;
68 			} else {
69 				uiSize = mbi.RegionSize;
70 				return;
71 			}
72 		}
73 	}
74 
75 	if (a_ucData) {
76 		UnmapViewOfFile(a_ucData);
77 		a_ucData = NULL;
78 	}
79 	if (d->hMemory) {
80 		CloseHandle(d->hMemory);
81 		d->hMemory = NULL;
82 	}
83 }
84 
~SharedMemory2()85 SharedMemory2::~SharedMemory2() {
86 	if (a_ucData)
87 		UnmapViewOfFile(a_ucData);
88 	if (d->hMemory)
89 		CloseHandle(d->hMemory);
90 
91 	delete d;
92 }
93 
systemRelease()94 void SharedMemory2::systemRelease() {
95 	// This doesn't really do anything on Win32, since it has delete-on-close semantics anyway
96 	if (d->hMemory) {
97 		CloseHandle(d->hMemory);
98 		d->hMemory = NULL;
99 	}
100 }
101