7#include <QtCore/private/qsystemerror_p.h>
24bool QLocalServerPrivate::addListener()
28 listeners.push_back(std::make_unique<Listener>());
29 auto &listener = listeners.back();
31 SECURITY_ATTRIBUTES sa;
32 sa.nLength =
sizeof(SECURITY_ATTRIBUTES);
33 sa.bInheritHandle = FALSE;
34 sa.lpSecurityDescriptor = 0;
44 pSD.
reset(
new SECURITY_DESCRIPTOR);
45 if (!InitializeSecurityDescriptor(pSD.
data(), SECURITY_DESCRIPTOR_REVISION)) {
46 setError(
"QLocalServerPrivate::addListener"_L1);
50 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
52 DWORD dwBufferSize = 0;
53 GetTokenInformation(hToken, TokenUser, 0, 0, &dwBufferSize);
54 tokenUserBuffer.
fill(0, dwBufferSize);
55 auto pTokenUser =
reinterpret_cast<PTOKEN_USER
>(tokenUserBuffer.
data());
56 if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwBufferSize, &dwBufferSize)) {
57 setError(
"QLocalServerPrivate::addListener"_L1);
63 GetTokenInformation(hToken, TokenPrimaryGroup, 0, 0, &dwBufferSize);
64 tokenGroupBuffer.
fill(0, dwBufferSize);
65 auto pTokenGroup =
reinterpret_cast<PTOKEN_PRIMARY_GROUP
>(tokenGroupBuffer.
data());
66 if (!GetTokenInformation(hToken, TokenPrimaryGroup, pTokenGroup, dwBufferSize, &dwBufferSize)) {
67 setError(
"QLocalServerPrivate::addListener"_L1);
73#ifdef QLOCALSERVER_DEBUG
76 SID_NAME_USE groupNameUse;
78 LookupAccountSid(0, pTokenGroup->PrimaryGroup, 0, &groupNameSize, 0, &domainNameSize, &groupNameUse);
81 if (LookupAccountSid(0, pTokenGroup->PrimaryGroup, groupName.
data(), &groupNameSize, domainName.
data(), &domainNameSize, &groupNameUse)) {
84 if (ConvertSidToStringSid(pTokenGroup->PrimaryGroup, &groupNameSid)) {
86 LocalFree(groupNameSid);
90 SID_IDENTIFIER_AUTHORITY WorldAuth = { SECURITY_WORLD_SID_AUTHORITY };
91 if (!AllocateAndInitializeSid(&WorldAuth, 1, SECURITY_WORLD_RID,
94 setError(
"QLocalServerPrivate::addListener"_L1);
99 DWORD aclSize =
sizeof(ACL) + ((
sizeof(ACCESS_ALLOWED_ACE)) * 3);
100 aclSize += GetLengthSid(pTokenUser->User.Sid) -
sizeof(DWORD);
101 aclSize += GetLengthSid(pTokenGroup->PrimaryGroup) -
sizeof(DWORD);
102 aclSize += GetLengthSid(worldSID) -
sizeof(DWORD);
103 aclSize = (aclSize + (
sizeof(DWORD) - 1)) & 0xfffffffc;
105 aclBuffer.
fill(0, aclSize);
106 auto acl =
reinterpret_cast<PACL
>(aclBuffer.
data());
107 InitializeAcl(acl, aclSize, ACL_REVISION_DS);
110 if (!AddAccessAllowedAce(acl, ACL_REVISION, FILE_ALL_ACCESS, pTokenUser->User.Sid)) {
111 setError(
"QLocalServerPrivate::addListener"_L1);
117 if (!AddAccessAllowedAce(acl, ACL_REVISION, FILE_ALL_ACCESS, pTokenGroup->PrimaryGroup)) {
118 setError(
"QLocalServerPrivate::addListener"_L1);
124 if (!AddAccessAllowedAce(acl, ACL_REVISION, FILE_ALL_ACCESS, worldSID)) {
125 setError(
"QLocalServerPrivate::addListener"_L1);
130 SetSecurityDescriptorOwner(pSD.
data(), pTokenUser->User.Sid, FALSE);
131 SetSecurityDescriptorGroup(pSD.
data(), pTokenGroup->PrimaryGroup, FALSE);
132 if (!SetSecurityDescriptorDacl(pSD.
data(), TRUE, acl, FALSE)) {
133 setError(
"QLocalServerPrivate::addListener"_L1);
138 sa.lpSecurityDescriptor = pSD.
data();
141 listener->handle = CreateNamedPipe(
143 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
147 PIPE_UNLIMITED_INSTANCES,
153 if (listener->handle == INVALID_HANDLE_VALUE) {
154 setError(
"QLocalServerPrivate::addListener"_L1);
155 listeners.pop_back();
162 memset(&listener->overlapped, 0,
sizeof(OVERLAPPED));
163 listener->overlapped.hEvent = eventHandle;
167 if (!ConnectNamedPipe(listener->handle, &listener->overlapped)) {
168 switch (GetLastError()) {
169 case ERROR_IO_PENDING:
170 listener->connected =
false;
172 case ERROR_PIPE_CONNECTED:
173 listener->connected =
true;
176 CloseHandle(listener->handle);
177 setError(
"QLocalServerPrivate::addListener"_L1);
178 listeners.pop_back();
182 Q_ASSERT_X(
false,
"QLocalServerPrivate::addListener",
"The impossible happened");
183 SetEvent(eventHandle);
190 int windowsError = GetLastError();
209 const auto pipePath =
"\\\\.\\pipe\\"_L1;
210 if (
name.startsWith(pipePath))
218 eventHandle = CreateEvent(NULL, TRUE, FALSE, NULL);
232 qWarning(
"QLocalServer::listen(qintptr) is not supported on Windows QTBUG-24230");
246 ResetEvent(eventHandle);
250 for (
size_t i = 0;
i < listeners.size(); ) {
253 || GetOverlappedResult(
handle, &listeners[
i]->overlapped, &dummy, FALSE))
255 listeners.erase(listeners.begin() +
i);
260 connectionEventNotifier->setEnabled(
false);
267 if (GetLastError() != ERROR_IO_INCOMPLETE) {
269 setError(
"QLocalServerPrivate::_q_onNewConnection"_L1);
281 connectionEventNotifier->setEnabled(
false);
282 connectionEventNotifier->deleteLater();
283 connectionEventNotifier = 0;
284 CloseHandle(eventHandle);
285 for (
size_t i = 0;
i < listeners.size(); ++
i)
286 CloseHandle(listeners[
i]->
handle);
296 DWORD
result = WaitForSingleObject(eventHandle, (msecs == -1) ? INFINITE : msecs);
297 if (
result == WAIT_TIMEOUT) {
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
QByteArray & fill(char c, qsizetype size=-1)
Sets every byte in the byte array to ch.
qsizetype size() const noexcept
bool isEmpty() const noexcept
void waitForNewConnection(int msec, bool *timedOut)
static bool removeServer(const QString &name)
void setError(const QString &function)
QQueue< QLocalSocket * > pendingConnections
void _q_onNewConnection()
QAbstractSocket::SocketError error
int maxPendingConnections
bool listen(const QString &name)
The QLocalServer class provides a local socket based server.
T * data() const noexcept
Returns the value of the pointer referenced by this object.
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
const ushort * utf16() const
Returns the QString as a '\0\'-terminated array of unsigned shorts.
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
Combined button and popup list for selecting options.
Q_DECL_COLD_FUNCTION Q_CORE_EXPORT QString qt_error_string(int errorCode=-1)
GLuint64 GLenum void * handle
GLdouble GLdouble GLdouble GLdouble q
#define Q_ASSERT_X(cond, x, msg)