summaryrefslogtreecommitdiff
path: root/cpp/src/qpid/sys/windows
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/qpid/sys/windows')
-rw-r--r--cpp/src/qpid/sys/windows/AsynchIO.cpp71
-rwxr-xr-xcpp/src/qpid/sys/windows/AsynchIoResult.h6
-rwxr-xr-xcpp/src/qpid/sys/windows/IocpPoller.cpp6
-rw-r--r--cpp/src/qpid/sys/windows/SCM.cpp332
-rw-r--r--cpp/src/qpid/sys/windows/SCM.h111
-rw-r--r--cpp/src/qpid/sys/windows/Shlib.cpp3
-rwxr-xr-x[-rw-r--r--]cpp/src/qpid/sys/windows/Socket.cpp188
-rw-r--r--cpp/src/qpid/sys/windows/SocketAddress.cpp120
-rw-r--r--cpp/src/qpid/sys/windows/SslAsynchIO.h3
-rwxr-xr-xcpp/src/qpid/sys/windows/StrError.cpp7
-rwxr-xr-xcpp/src/qpid/sys/windows/Thread.cpp285
-rw-r--r--cpp/src/qpid/sys/windows/Time.cpp36
-rw-r--r--cpp/src/qpid/sys/windows/mingw32_compat.h39
-rw-r--r--cpp/src/qpid/sys/windows/uuid.cpp6
14 files changed, 217 insertions, 996 deletions
diff --git a/cpp/src/qpid/sys/windows/AsynchIO.cpp b/cpp/src/qpid/sys/windows/AsynchIO.cpp
index 30378d4c5f..38d8842521 100644
--- a/cpp/src/qpid/sys/windows/AsynchIO.cpp
+++ b/cpp/src/qpid/sys/windows/AsynchIO.cpp
@@ -30,7 +30,6 @@
#include "qpid/log/Statement.h"
#include "qpid/sys/windows/check.h"
-#include "qpid/sys/windows/mingw32_compat.h"
#include <boost/thread/once.hpp>
@@ -47,13 +46,16 @@ namespace {
/*
* The function pointers for AcceptEx and ConnectEx need to be looked up
- * at run time.
+ * at run time. Make sure this is done only once.
*/
-const LPFN_ACCEPTEX lookUpAcceptEx(const qpid::sys::Socket& s) {
- SOCKET h = toSocketHandle(s);
+boost::once_flag lookUpAcceptExOnce = BOOST_ONCE_INIT;
+LPFN_ACCEPTEX fnAcceptEx = 0;
+typedef void (*lookUpFunc)(const qpid::sys::Socket &);
+
+void lookUpAcceptEx() {
+ SOCKET h = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
GUID guidAcceptEx = WSAID_ACCEPTEX;
DWORD dwBytes = 0;
- LPFN_ACCEPTEX fnAcceptEx;
WSAIoctl(h,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&guidAcceptEx,
@@ -63,9 +65,9 @@ const LPFN_ACCEPTEX lookUpAcceptEx(const qpid::sys::Socket& s) {
&dwBytes,
NULL,
NULL);
+ closesocket(h);
if (fnAcceptEx == 0)
throw qpid::Exception(QPID_MSG("Failed to look up AcceptEx"));
- return fnAcceptEx;
}
}
@@ -92,15 +94,18 @@ private:
AsynchAcceptor::Callback acceptedCallback;
const Socket& socket;
- const LPFN_ACCEPTEX fnAcceptEx;
};
AsynchAcceptor::AsynchAcceptor(const Socket& s, Callback callback)
: acceptedCallback(callback),
- socket(s),
- fnAcceptEx(lookUpAcceptEx(s)) {
+ socket(s) {
s.setNonblocking();
+#if (BOOST_VERSION >= 103500) /* boost 1.35 or later reversed the args */
+ boost::call_once(lookUpAcceptExOnce, lookUpAcceptEx);
+#else
+ boost::call_once(lookUpAcceptEx, lookUpAcceptExOnce);
+#endif
}
AsynchAcceptor::~AsynchAcceptor()
@@ -109,8 +114,7 @@ AsynchAcceptor::~AsynchAcceptor()
}
void AsynchAcceptor::start(Poller::shared_ptr poller) {
- PollerHandle ph = PollerHandle(socket);
- poller->monitorHandle(ph, Poller::INPUT);
+ poller->monitorHandle(PollerHandle(socket), Poller::INPUT);
restart ();
}
@@ -118,26 +122,25 @@ void AsynchAcceptor::restart(void) {
DWORD bytesReceived = 0; // Not used, needed for AcceptEx API
AsynchAcceptResult *result = new AsynchAcceptResult(acceptedCallback,
this,
- socket);
+ toSocketHandle(socket));
BOOL status;
- status = fnAcceptEx(toSocketHandle(socket),
- toSocketHandle(*result->newSocket),
- result->addressBuffer,
- 0,
- AsynchAcceptResult::SOCKADDRMAXLEN,
- AsynchAcceptResult::SOCKADDRMAXLEN,
- &bytesReceived,
- result->overlapped());
+ status = ::fnAcceptEx(toSocketHandle(socket),
+ toSocketHandle(*result->newSocket),
+ result->addressBuffer,
+ 0,
+ AsynchAcceptResult::SOCKADDRMAXLEN,
+ AsynchAcceptResult::SOCKADDRMAXLEN,
+ &bytesReceived,
+ result->overlapped());
QPID_WINDOWS_CHECK_ASYNC_START(status);
}
AsynchAcceptResult::AsynchAcceptResult(AsynchAcceptor::Callback cb,
AsynchAcceptor *acceptor,
- const Socket& listener)
- : callback(cb), acceptor(acceptor),
- listener(toSocketHandle(listener)),
- newSocket(listener.createSameTypeSocket()) {
+ SOCKET listener)
+ : callback(cb), acceptor(acceptor), listener(listener) {
+ newSocket.reset (new Socket());
}
void AsynchAcceptResult::success(size_t /*bytesTransferred*/) {
@@ -151,7 +154,7 @@ void AsynchAcceptResult::success(size_t /*bytesTransferred*/) {
delete this;
}
-void AsynchAcceptResult::failure(int /*status*/) {
+void AsynchAcceptResult::failure(int status) {
//if (status != WSA_OPERATION_ABORTED)
// Can there be anything else? ;
delete this;
@@ -170,20 +173,20 @@ private:
FailedCallback failCallback;
const Socket& socket;
const std::string hostname;
- const std::string port;
+ const uint16_t port;
public:
AsynchConnector(const Socket& socket,
- const std::string& hostname,
- const std::string& port,
+ std::string hostname,
+ uint16_t port,
ConnectedCallback connCb,
FailedCallback failCb = 0);
void start(Poller::shared_ptr poller);
};
AsynchConnector::AsynchConnector(const Socket& sock,
- const std::string& hname,
- const std::string& p,
+ std::string hname,
+ uint16_t p,
ConnectedCallback connCb,
FailedCallback failCb) :
connCallback(connCb), failCallback(failCb), socket(sock),
@@ -213,8 +216,8 @@ AsynchAcceptor* AsynchAcceptor::create(const Socket& s,
}
AsynchConnector* qpid::sys::AsynchConnector::create(const Socket& s,
- const std::string& hostname,
- const std::string& port,
+ std::string hostname,
+ uint16_t port,
ConnectedCallback connCb,
FailedCallback failCb)
{
@@ -407,9 +410,8 @@ void AsynchIO::queueForDeletion() {
}
void AsynchIO::start(Poller::shared_ptr poller0) {
- PollerHandle ph = PollerHandle(socket);
poller = poller0;
- poller->monitorHandle(ph, Poller::INPUT);
+ poller->monitorHandle(PollerHandle(socket), Poller::INPUT);
if (writeQueue.size() > 0) // Already have data queued for write
notifyPendingWrite();
startReading();
@@ -582,6 +584,7 @@ void AsynchIO::notifyIdle(void) {
void AsynchIO::startWrite(AsynchIO::BufferBase* buff) {
writeInProgress = true;
InterlockedIncrement(&opsInProgress);
+ int writeCount = buff->byteCount-buff->dataCount;
AsynchWriteResult *result =
new AsynchWriteResult(boost::bind(&AsynchIO::completion, this, _1),
buff,
diff --git a/cpp/src/qpid/sys/windows/AsynchIoResult.h b/cpp/src/qpid/sys/windows/AsynchIoResult.h
index 27e4c22138..66c89efc11 100755
--- a/cpp/src/qpid/sys/windows/AsynchIoResult.h
+++ b/cpp/src/qpid/sys/windows/AsynchIoResult.h
@@ -83,22 +83,22 @@ class AsynchAcceptResult : public AsynchResult {
public:
AsynchAcceptResult(qpid::sys::AsynchAcceptor::Callback cb,
AsynchAcceptor *acceptor,
- const qpid::sys::Socket& listener);
+ SOCKET listener);
virtual void success (size_t bytesTransferred);
virtual void failure (int error);
private:
virtual void complete(void) {} // No-op for this class.
+ std::auto_ptr<qpid::sys::Socket> newSocket;
qpid::sys::AsynchAcceptor::Callback callback;
AsynchAcceptor *acceptor;
SOCKET listener;
- std::auto_ptr<qpid::sys::Socket> newSocket;
// AcceptEx needs a place to write the local and remote addresses
// when accepting the connection. Place those here; get enough for
// IPv6 addresses, even if the socket is IPv4.
- enum { SOCKADDRMAXLEN = sizeof(sockaddr_in6) + 16,
+ enum { SOCKADDRMAXLEN = sizeof sockaddr_in6 + 16,
SOCKADDRBUFLEN = 2 * SOCKADDRMAXLEN };
char addressBuffer[SOCKADDRBUFLEN];
};
diff --git a/cpp/src/qpid/sys/windows/IocpPoller.cpp b/cpp/src/qpid/sys/windows/IocpPoller.cpp
index 1805dd2cd8..d326ab02ac 100755
--- a/cpp/src/qpid/sys/windows/IocpPoller.cpp
+++ b/cpp/src/qpid/sys/windows/IocpPoller.cpp
@@ -152,9 +152,9 @@ void Poller::monitorHandle(PollerHandle& handle, Direction dir) {
}
// All no-ops...
-void Poller::unmonitorHandle(PollerHandle& /*handle*/, Direction /*dir*/) {}
-void Poller::registerHandle(PollerHandle& /*handle*/) {}
-void Poller::unregisterHandle(PollerHandle& /*handle*/) {}
+void Poller::unmonitorHandle(PollerHandle& handle, Direction dir) {}
+void Poller::registerHandle(PollerHandle& handle) {}
+void Poller::unregisterHandle(PollerHandle& handle) {}
Poller::Event Poller::wait(Duration timeout) {
DWORD timeoutMs = 0;
diff --git a/cpp/src/qpid/sys/windows/SCM.cpp b/cpp/src/qpid/sys/windows/SCM.cpp
deleted file mode 100644
index 4d2c74d4b9..0000000000
--- a/cpp/src/qpid/sys/windows/SCM.cpp
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include "qpid/log/Statement.h"
-#include "qpid/sys/windows/check.h"
-#include "SCM.h"
-
-#pragma comment(lib, "advapi32.lib")
-
-namespace {
-
-// Container that will close a SC_HANDLE upon destruction.
-class AutoServiceHandle {
-public:
- AutoServiceHandle(SC_HANDLE h_ = NULL) : h(h_) {}
- ~AutoServiceHandle() { if (h != NULL) ::CloseServiceHandle(h); }
- void release() { h = NULL; }
- void reset(SC_HANDLE newHandle)
- {
- if (h != NULL)
- ::CloseServiceHandle(h);
- h = newHandle;
- }
- operator SC_HANDLE() const { return h; }
-
-private:
- SC_HANDLE h;
-};
-
-}
-
-namespace qpid {
-namespace windows {
-
-SCM::SCM() : scmHandle(NULL)
-{
-}
-
-SCM::~SCM()
-{
- if (NULL != scmHandle)
- ::CloseServiceHandle(scmHandle);
-}
-
-/**
- * Install this executable as a service
- */
-void SCM::install(const string& serviceName,
- const string& serviceDesc,
- const string& args,
- DWORD startType,
- const string& account,
- const string& password,
- const string& depends)
-{
- // Handle dependent service name list; Windows wants a set of nul-separated
- // names ending with a double nul.
- string depends2 = depends;
- if (!depends2.empty()) {
- // CDL to null delimiter w/ trailing double null
- size_t p = 0;
- while ((p = depends2.find_first_of( ',', p)) != string::npos)
- depends2.replace(p, 1, 1, '\0');
- depends2.push_back('\0');
- depends2.push_back('\0');
- }
-
-#if 0
- // I'm nervous about adding a user/password check here. Is this a
- // potential attack vector, letting users check passwords without
- // control? -Steve Huston, Feb 24, 2011
-
- // Validate account, password
- HANDLE hToken = NULL;
- bool logStatus = false;
- if (!account.empty() && !password.empty() &&
- !(logStatus = ::LogonUserA(account.c_str(),
- "",
- password.c_str(),
- LOGON32_LOGON_NETWORK,
- LOGON32_PROVIDER_DEFAULT,
- &hToken ) != 0))
- std::cout << "warning: supplied account & password failed with LogonUser." << std::endl;
- if (logStatus)
- ::CloseHandle(hToken);
-#endif
-
- // Get fully qualified .exe name
- char myPath[MAX_PATH];
- DWORD myPathLength = ::GetModuleFileName(NULL, myPath, MAX_PATH);
- QPID_WINDOWS_CHECK_NOT(myPathLength, 0);
- string imagePath(myPath, myPathLength);
- if (!args.empty())
- imagePath += " " + args;
-
- // Ensure there's a handle to the SCM database.
- openSvcManager();
-
- // Create the service
- SC_HANDLE svcHandle;
- svcHandle = ::CreateService(scmHandle, // SCM database
- serviceName.c_str(), // name of service
- serviceDesc.c_str(), // name to display
- SERVICE_ALL_ACCESS, // desired access
- SERVICE_WIN32_OWN_PROCESS, // service type
- startType, // start type
- SERVICE_ERROR_NORMAL, // error cntrl type
- imagePath.c_str(), // path to service's binary w/ optional arguments
- NULL, // no load ordering group
- NULL, // no tag identifier
- depends2.empty() ? NULL : depends2.c_str(),
- account.empty() ? NULL : account.c_str(), // account name, or NULL for LocalSystem
- password.empty() ? NULL : password.c_str()); // password, or NULL for none
- QPID_WINDOWS_CHECK_NULL(svcHandle);
- ::CloseServiceHandle(svcHandle);
- QPID_LOG(info, "Service installed successfully");
-}
-
-/**
- *
- */
-void SCM::uninstall(const string& serviceName)
-{
- // Ensure there's a handle to the SCM database.
- openSvcManager();
- AutoServiceHandle svc(::OpenService(scmHandle,
- serviceName.c_str(),
- DELETE));
- QPID_WINDOWS_CHECK_NULL((SC_HANDLE)svc);
- QPID_WINDOWS_CHECK_NOT(::DeleteService(svc), 0);
- QPID_LOG(info, "Service deleted successfully.");
-}
-
-/**
- * Attempt to start the service.
- */
-void SCM::start(const string& serviceName)
-{
- // Ensure we have a handle to the SCM database.
- openSvcManager();
-
- // Get a handle to the service.
- AutoServiceHandle svc(::OpenService(scmHandle,
- serviceName.c_str(),
- SERVICE_ALL_ACCESS));
- QPID_WINDOWS_CHECK_NULL(svc);
-
- // Check the status in case the service is not stopped.
- DWORD state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING);
- if (state == SERVICE_STOP_PENDING)
- throw qpid::Exception("Timed out waiting for running service to stop.");
-
- // Attempt to start the service.
- QPID_WINDOWS_CHECK_NOT(::StartService(svc, 0, NULL), 0);
-
- QPID_LOG(info, "Service start pending...");
-
- // Check the status until the service is no longer start pending.
- state = waitForStateChangeFrom(svc, SERVICE_START_PENDING);
- // Determine whether the service is running.
- if (state == SERVICE_RUNNING) {
- QPID_LOG(info, "Service started successfully");
- }
- else {
- throw qpid::Exception(QPID_MSG("Service not yet running; state now " << state));
- }
-}
-
-/**
- *
- */
-void SCM::stop(const string& serviceName)
-{
- // Ensure a handle to the SCM database.
- openSvcManager();
-
- // Get a handle to the service.
- AutoServiceHandle svc(::OpenService(scmHandle,
- serviceName.c_str(),
- SERVICE_STOP | SERVICE_QUERY_STATUS |
- SERVICE_ENUMERATE_DEPENDENTS));
- QPID_WINDOWS_CHECK_NULL(svc);
-
- // Make sure the service is not already stopped; if it's stop-pending,
- // wait for it to finalize.
- DWORD state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING);
- if (state == SERVICE_STOPPED) {
- QPID_LOG(info, "Service is already stopped");
- return;
- }
-
- // If the service is running, dependencies must be stopped first.
- std::auto_ptr<ENUM_SERVICE_STATUS> deps;
- DWORD numDeps = getDependentServices(svc, deps);
- for (DWORD i = 0; i < numDeps; i++)
- stop(deps.get()[i].lpServiceName);
-
- // Dependents stopped; send a stop code to the service.
- SERVICE_STATUS_PROCESS ssp;
- if (!::ControlService(svc, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS)&ssp))
- throw qpid::Exception(QPID_MSG("Stopping " << serviceName << ": " <<
- qpid::sys::strError(::GetLastError())));
-
- // Wait for the service to stop.
- state = waitForStateChangeFrom(svc, SERVICE_STOP_PENDING);
- if (state == SERVICE_STOPPED)
- QPID_LOG(info, QPID_MSG("Service " << serviceName <<
- " stopped successfully."));
-}
-
-/**
- *
- */
-void SCM::openSvcManager()
-{
- if (NULL != scmHandle)
- return;
-
- scmHandle = ::OpenSCManager(NULL, // local computer
- NULL, // ServicesActive database
- SC_MANAGER_ALL_ACCESS); // Rights
- QPID_WINDOWS_CHECK_NULL(scmHandle);
-}
-
-DWORD SCM::waitForStateChangeFrom(SC_HANDLE svc, DWORD originalState)
-{
- SERVICE_STATUS_PROCESS ssStatus;
- DWORD bytesNeeded;
- DWORD waitTime;
- if (!::QueryServiceStatusEx(svc, // handle to service
- SC_STATUS_PROCESS_INFO, // information level
- (LPBYTE)&ssStatus, // address of structure
- sizeof(ssStatus), // size of structure
- &bytesNeeded)) // size needed if buffer is too small
- throw QPID_WINDOWS_ERROR(::GetLastError());
-
- // Save the tick count and initial checkpoint.
- DWORD startTickCount = ::GetTickCount();
- DWORD oldCheckPoint = ssStatus.dwCheckPoint;
-
- // Wait for the service to change out of the noted state.
- while (ssStatus.dwCurrentState == originalState) {
- // Do not wait longer than the wait hint. A good interval is
- // one-tenth of the wait hint but not less than 1 second
- // and not more than 10 seconds.
- waitTime = ssStatus.dwWaitHint / 10;
- if (waitTime < 1000)
- waitTime = 1000;
- else if (waitTime > 10000)
- waitTime = 10000;
-
- ::Sleep(waitTime);
-
- // Check the status until the service is no longer stop pending.
- if (!::QueryServiceStatusEx(svc,
- SC_STATUS_PROCESS_INFO,
- (LPBYTE) &ssStatus,
- sizeof(ssStatus),
- &bytesNeeded))
- throw QPID_WINDOWS_ERROR(::GetLastError());
-
- if (ssStatus.dwCheckPoint > oldCheckPoint) {
- // Continue to wait and check.
- startTickCount = ::GetTickCount();
- oldCheckPoint = ssStatus.dwCheckPoint;
- } else {
- if ((::GetTickCount() - startTickCount) > ssStatus.dwWaitHint)
- break;
- }
- }
- return ssStatus.dwCurrentState;
-}
-
-/**
- * Get the services that depend on @arg svc. All dependent service info
- * is returned in an array of ENUM_SERVICE_STATUS structures via @arg deps.
- *
- * @retval The number of dependent services.
- */
-DWORD SCM::getDependentServices(SC_HANDLE svc,
- std::auto_ptr<ENUM_SERVICE_STATUS>& deps)
-{
- DWORD bytesNeeded;
- DWORD numEntries;
-
- // Pass a zero-length buffer to get the required buffer size.
- if (::EnumDependentServices(svc,
- SERVICE_ACTIVE,
- 0,
- 0,
- &bytesNeeded,
- &numEntries)) {
- // If the Enum call succeeds, then there are no dependent
- // services, so do nothing.
- return 0;
- }
-
- if (::GetLastError() != ERROR_MORE_DATA)
- throw QPID_WINDOWS_ERROR((::GetLastError()));
-
- // Allocate a buffer for the dependencies.
- deps.reset((LPENUM_SERVICE_STATUS)(new char[bytesNeeded]));
- // Enumerate the dependencies.
- if (!::EnumDependentServices(svc,
- SERVICE_ACTIVE,
- deps.get(),
- bytesNeeded,
- &bytesNeeded,
- &numEntries))
- throw QPID_WINDOWS_ERROR((::GetLastError()));
- return numEntries;
-}
-
-} } // namespace qpid::windows
diff --git a/cpp/src/qpid/sys/windows/SCM.h b/cpp/src/qpid/sys/windows/SCM.h
deleted file mode 100644
index 8e94ef83c7..0000000000
--- a/cpp/src/qpid/sys/windows/SCM.h
+++ /dev/null
@@ -1,111 +0,0 @@
-#ifndef WINDOWS_SCM_H
-#define WINDOWS_SCM_H
-
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#include <memory>
-#include <string>
-using std::string;
-
-#ifdef UNICODE
-#undef UNICODE
-#endif
-
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-
-#include <windows.h>
-
-#include "qpid/CommonImportExport.h"
-
-namespace qpid {
-namespace windows {
-
-/**
- * @class SCM
- *
- * Access the Windows Service Control Manager.
- */
-class SCM
-{
-public:
- QPID_COMMON_EXTERN SCM();
- QPID_COMMON_EXTERN ~SCM();
-
- /**
- * Install this executable as a service
- *
- * @param serviceName The name of the service
- * @param serviceDesc Description of the service's purpose
- * @param args The argument list to pass into the service
- * @param startType The start type: SERVICE_DEMAND_START,
- * SERVICE_AUTO_START, SERVICE_DISABLED
- * @param account If not empty, the account name to install this
- * service under
- * @param password If not empty, the account password to install this
- * service with
- * @param depends If not empty, a comma delimited list of services
- * that must start before this one
- */
- QPID_COMMON_EXTERN void install(const string& serviceName,
- const string& serviceDesc,
- const string& args,
- DWORD startType = SERVICE_DEMAND_START,
- const string& account = "NT AUTHORITY\\LocalSystem",
- const string& password = "",
- const string& depends = "");
-
- /**
- * Uninstall this executable as a service
- *
- * @param serviceName the name of the service
- */
- QPID_COMMON_EXTERN void uninstall(const string& serviceName);
-
- /**
- * Start the specified service
- *
- * @param serviceName the name of the service
- */
- QPID_COMMON_EXTERN void start(const string& serviceName);
-
- /**
- * Stop the specified service
- *
- * @param serviceName the name of the service
- */
- QPID_COMMON_EXTERN void stop(const string &serviceName);
-
-private:
- SC_HANDLE scmHandle;
-
- void openSvcManager();
- DWORD waitForStateChangeFrom(SC_HANDLE svc, DWORD originalState);
- DWORD getDependentServices(SC_HANDLE svc,
- std::auto_ptr<ENUM_SERVICE_STATUS>& deps);
-
-};
-
-}} // namespace qpid::windows
-
-#endif /* #ifndef WINDOWS_SCM_H */
diff --git a/cpp/src/qpid/sys/windows/Shlib.cpp b/cpp/src/qpid/sys/windows/Shlib.cpp
index ba18747eb4..38027de93f 100644
--- a/cpp/src/qpid/sys/windows/Shlib.cpp
+++ b/cpp/src/qpid/sys/windows/Shlib.cpp
@@ -44,8 +44,7 @@ void Shlib::unload() {
}
void* Shlib::getSymbol(const char* name) {
- // Double cast avoids warning about casting function pointer to object
- void *sym = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(GetProcAddress(static_cast<HMODULE>(handle), name)));
+ void* sym = GetProcAddress(static_cast<HMODULE>(handle), name);
if (sym == NULL)
throw QPID_WINDOWS_ERROR(GetLastError());
return sym;
diff --git a/cpp/src/qpid/sys/windows/Socket.cpp b/cpp/src/qpid/sys/windows/Socket.cpp
index 1fa4768329..11fb8b4133 100644..100755
--- a/cpp/src/qpid/sys/windows/Socket.cpp
+++ b/cpp/src/qpid/sys/windows/Socket.cpp
@@ -20,18 +20,19 @@
*/
#include "qpid/sys/Socket.h"
-
#include "qpid/sys/SocketAddress.h"
-#include "qpid/sys/windows/check.h"
#include "qpid/sys/windows/IoHandlePrivate.h"
+#include "qpid/sys/windows/check.h"
+#include "qpid/sys/Time.h"
-// Ensure we get all of winsock2.h
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#endif
+#include <cstdlib>
+#include <string.h>
#include <winsock2.h>
+#include <boost/format.hpp>
+#include <boost/lexical_cast.hpp>
+
// Need to initialize WinSock. Ideally, this would be a singleton or embedded
// in some one-time initialization function. I tried boost singleton and could
// not get it to compile (and others located in google had the same problem).
@@ -83,30 +84,53 @@ namespace sys {
namespace {
-std::string getName(SOCKET fd, bool local)
+std::string getName(SOCKET fd, bool local, bool includeService = false)
{
- ::sockaddr_storage name_s; // big enough for any socket address
- ::sockaddr* name = (::sockaddr*)&name_s;
- ::socklen_t namelen = sizeof(name_s);
-
+ sockaddr_in name; // big enough for any socket address
+ socklen_t namelen = sizeof(name);
if (local) {
- QPID_WINSOCK_CHECK(::getsockname(fd, name, &namelen));
+ QPID_WINSOCK_CHECK(::getsockname(fd, (sockaddr*)&name, &namelen));
} else {
- QPID_WINSOCK_CHECK(::getpeername(fd, name, &namelen));
+ QPID_WINSOCK_CHECK(::getpeername(fd, (sockaddr*)&name, &namelen));
}
- return SocketAddress::asString(name, namelen);
+ char servName[NI_MAXSERV];
+ char dispName[NI_MAXHOST];
+ if (includeService) {
+ if (int rc = ::getnameinfo((sockaddr*)&name, namelen,
+ dispName, sizeof(dispName),
+ servName, sizeof(servName),
+ NI_NUMERICHOST | NI_NUMERICSERV) != 0)
+ throw qpid::Exception(QPID_MSG(gai_strerror(rc)));
+ return std::string(dispName) + ":" + std::string(servName);
+ } else {
+ if (int rc = ::getnameinfo((sockaddr*)&name, namelen,
+ dispName, sizeof(dispName),
+ 0, 0,
+ NI_NUMERICHOST) != 0)
+ throw qpid::Exception(QPID_MSG(gai_strerror(rc)));
+ return dispName;
+ }
}
-uint16_t getLocalPort(int fd)
+std::string getService(SOCKET fd, bool local)
{
- ::sockaddr_storage name_s; // big enough for any socket address
- ::sockaddr* name = (::sockaddr*)&name_s;
- ::socklen_t namelen = sizeof(name_s);
-
- QPID_WINSOCK_CHECK(::getsockname(fd, name, &namelen));
+ sockaddr_in name; // big enough for any socket address
+ socklen_t namelen = sizeof(name);
+
+ if (local) {
+ QPID_WINSOCK_CHECK(::getsockname(fd, (sockaddr*)&name, &namelen));
+ } else {
+ QPID_WINSOCK_CHECK(::getpeername(fd, (sockaddr*)&name, &namelen));
+ }
- return SocketAddress::getPort(name);
+ char servName[NI_MAXSERV];
+ if (int rc = ::getnameinfo((sockaddr*)&name, namelen,
+ 0, 0,
+ servName, sizeof(servName),
+ NI_NUMERICHOST | NI_NUMERICSERV) != 0)
+ throw qpid::Exception(QPID_MSG(gai_strerror(rc)));
+ return servName;
}
} // namespace
@@ -114,7 +138,13 @@ Socket::Socket() :
IOHandle(new IOHandlePrivate),
nonblocking(false),
nodelay(false)
-{}
+{
+ SOCKET& socket = impl->fd;
+ if (socket != INVALID_SOCKET) Socket::close();
+ SOCKET s = ::socket (PF_INET, SOCK_STREAM, 0);
+ if (s == INVALID_SOCKET) throw QPID_WINDOWS_ERROR(WSAGetLastError());
+ socket = s;
+}
Socket::Socket(IOHandlePrivate* h) :
IOHandle(h),
@@ -122,7 +152,8 @@ Socket::Socket(IOHandlePrivate* h) :
nodelay(false)
{}
-void Socket::createSocket(const SocketAddress& sa) const
+void
+Socket::createSocket(const SocketAddress& sa) const
{
SOCKET& socket = impl->fd;
if (socket != INVALID_SOCKET) Socket::close();
@@ -137,24 +168,24 @@ void Socket::createSocket(const SocketAddress& sa) const
if (nonblocking) setNonblocking();
if (nodelay) setTcpNoDelay();
} catch (std::exception&) {
- ::closesocket(s);
+ closesocket(s);
socket = INVALID_SOCKET;
throw;
}
}
-Socket* Socket::createSameTypeSocket() const {
- SOCKET& socket = impl->fd;
- // Socket currently has no actual socket attached
- if (socket == INVALID_SOCKET)
- return new Socket;
-
- ::sockaddr_storage sa;
- ::socklen_t salen = sizeof(sa);
- QPID_WINSOCK_CHECK(::getsockname(socket, (::sockaddr*)&sa, &salen));
- SOCKET s = ::socket(sa.ss_family, SOCK_STREAM, 0); // Currently only work with SOCK_STREAM
- if (s == INVALID_SOCKET) throw QPID_WINDOWS_ERROR(WSAGetLastError());
- return new Socket(new IOHandlePrivate(s));
+void Socket::setTimeout(const Duration& interval) const
+{
+ const SOCKET& socket = impl->fd;
+ int64_t nanosecs = interval;
+ nanosecs /= (1000 * 1000); // nsecs -> usec -> msec
+ int msec = 0;
+ if (nanosecs > std::numeric_limits<int>::max())
+ msec = std::numeric_limits<int>::max();
+ else
+ msec = static_cast<int>(nanosecs);
+ setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&msec, sizeof(msec));
+ setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&msec, sizeof(msec));
}
void Socket::setNonblocking() const {
@@ -162,25 +193,30 @@ void Socket::setNonblocking() const {
QPID_WINSOCK_CHECK(ioctlsocket(impl->fd, FIONBIO, &nonblock));
}
-void Socket::connect(const std::string& host, const std::string& port) const
+void Socket::connect(const std::string& host, uint16_t port) const
{
- SocketAddress sa(host, port);
+ SocketAddress sa(host, boost::lexical_cast<std::string>(port));
connect(sa);
}
void
Socket::connect(const SocketAddress& addr) const
{
- peername = addr.asString(false);
-
- createSocket(addr);
-
const SOCKET& socket = impl->fd;
- int err;
+ const addrinfo *addrs = &(getAddrInfo(addr));
+ int error = 0;
WSASetLastError(0);
- if ((::connect(socket, getAddrInfo(addr).ai_addr, getAddrInfo(addr).ai_addrlen) != 0) &&
- ((err = ::WSAGetLastError()) != WSAEWOULDBLOCK))
- throw qpid::Exception(QPID_MSG(strError(err) << ": " << peername));
+ while (addrs != 0) {
+ if ((::connect(socket, addrs->ai_addr, addrs->ai_addrlen) == 0) ||
+ (WSAGetLastError() == WSAEWOULDBLOCK))
+ break;
+ // Error... save this error code and see if there are other address
+ // to try before throwing the exception.
+ error = WSAGetLastError();
+ addrs = addrs->ai_next;
+ }
+ if (error)
+ throw qpid::Exception(QPID_MSG(strError(error) << ": " << connectname));
}
void
@@ -211,26 +247,24 @@ int Socket::read(void *buf, size_t count) const
return received;
}
-int Socket::listen(const std::string& host, const std::string& port, int backlog) const
-{
- SocketAddress sa(host, port);
- return listen(sa, backlog);
-}
-
-int Socket::listen(const SocketAddress& addr, int backlog) const
+int Socket::listen(uint16_t port, int backlog) const
{
- createSocket(addr);
-
const SOCKET& socket = impl->fd;
BOOL yes=1;
QPID_WINSOCK_CHECK(setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)));
-
- if (::bind(socket, getAddrInfo(addr).ai_addr, getAddrInfo(addr).ai_addrlen) == SOCKET_ERROR)
- throw Exception(QPID_MSG("Can't bind to " << addr.asString() << ": " << strError(WSAGetLastError())));
+ struct sockaddr_in name;
+ memset(&name, 0, sizeof(name));
+ name.sin_family = AF_INET;
+ name.sin_port = htons(port);
+ name.sin_addr.s_addr = 0;
+ if (::bind(socket, (struct sockaddr*)&name, sizeof(name)) == SOCKET_ERROR)
+ throw Exception(QPID_MSG("Can't bind to port " << port << ": " << strError(WSAGetLastError())));
if (::listen(socket, backlog) == SOCKET_ERROR)
- throw Exception(QPID_MSG("Can't listen on " <<addr.asString() << ": " << strError(WSAGetLastError())));
-
- return getLocalPort(socket);
+ throw Exception(QPID_MSG("Can't listen on port " << port << ": " << strError(WSAGetLastError())));
+
+ socklen_t namelen = sizeof(name);
+ QPID_WINSOCK_CHECK(::getsockname(socket, (struct sockaddr*)&name, &namelen));
+ return ntohs(name.sin_port);
}
Socket* Socket::accept() const
@@ -243,20 +277,36 @@ Socket* Socket::accept() const
else throw QPID_WINDOWS_ERROR(WSAGetLastError());
}
+std::string Socket::getSockname() const
+{
+ return getName(impl->fd, true);
+}
+
+std::string Socket::getPeername() const
+{
+ return getName(impl->fd, false);
+}
+
std::string Socket::getPeerAddress() const
{
- if (peername.empty()) {
- peername = getName(impl->fd, false);
- }
- return peername;
+ if (!connectname.empty())
+ return std::string (connectname);
+ return getName(impl->fd, false, true);
}
std::string Socket::getLocalAddress() const
{
- if (localname.empty()) {
- localname = getName(impl->fd, true);
- }
- return localname;
+ return getName(impl->fd, true, true);
+}
+
+uint16_t Socket::getLocalPort() const
+{
+ return atoi(getService(impl->fd, true).c_str());
+}
+
+uint16_t Socket::getRemotePort() const
+{
+ return atoi(getService(impl->fd, true).c_str());
}
int Socket::getError() const
diff --git a/cpp/src/qpid/sys/windows/SocketAddress.cpp b/cpp/src/qpid/sys/windows/SocketAddress.cpp
index 77bbf85810..501cff1297 100644
--- a/cpp/src/qpid/sys/windows/SocketAddress.cpp
+++ b/cpp/src/qpid/sys/windows/SocketAddress.cpp
@@ -21,13 +21,7 @@
#include "qpid/sys/SocketAddress.h"
-#include "qpid/Exception.h"
-#include "qpid/Msg.h"
-
-// Ensure we get all of winsock2.h
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#endif
+#include "qpid/sys/windows/check.h"
#include <winsock2.h>
#include <ws2tcpip.h>
@@ -41,111 +35,37 @@ SocketAddress::SocketAddress(const std::string& host0, const std::string& port0)
port(port0),
addrInfo(0)
{
-}
-
-SocketAddress::SocketAddress(const SocketAddress& sa) :
- host(sa.host),
- port(sa.port),
- addrInfo(0)
-{
-}
-
-SocketAddress& SocketAddress::operator=(const SocketAddress& sa)
-{
- SocketAddress temp(sa);
-
- std::swap(temp, *this);
- return *this;
-}
-
-SocketAddress::~SocketAddress()
-{
- if (addrInfo) {
- ::freeaddrinfo(addrInfo);
+ ::addrinfo hints;
+ ::memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET; // In order to allow AF_INET6 we'd have to change createTcp() as well
+ hints.ai_socktype = SOCK_STREAM;
+
+ const char* node = 0;
+ if (host.empty()) {
+ hints.ai_flags |= AI_PASSIVE;
+ } else {
+ node = host.c_str();
}
-}
+ const char* service = port.empty() ? "0" : port.c_str();
-std::string SocketAddress::asString(::sockaddr const * const addr, size_t addrlen)
-{
- char servName[NI_MAXSERV];
- char dispName[NI_MAXHOST];
- if (int rc=::getnameinfo(addr, addrlen,
- dispName, sizeof(dispName),
- servName, sizeof(servName),
- NI_NUMERICHOST | NI_NUMERICSERV) != 0)
- throw qpid::Exception(QPID_MSG(gai_strerror(rc)));
- std::string s;
- switch (addr->sa_family) {
- case AF_INET: s += dispName; break;
- case AF_INET6: s += "["; s += dispName; s+= "]"; break;
- default: throw Exception(QPID_MSG("Unexpected socket type"));
- }
- s += ":";
- s += servName;
- return s;
+ int n = ::getaddrinfo(node, service, &hints, &addrInfo);
+ if (n != 0)
+ throw Exception(QPID_MSG("Cannot resolve " << host << ": " << ::gai_strerror(n)));
}
-uint16_t SocketAddress::getPort(::sockaddr const * const addr)
+SocketAddress::~SocketAddress()
{
- switch (addr->sa_family) {
- case AF_INET: return ntohs(((::sockaddr_in*)addr)->sin_port);
- case AF_INET6: return ntohs(((::sockaddr_in6*)addr)->sin6_port);
- default:throw Exception(QPID_MSG("Unexpected socket type"));
- }
+ ::freeaddrinfo(addrInfo);
}
-std::string SocketAddress::asString(bool numeric) const
+std::string SocketAddress::asString() const
{
- if (!numeric)
- return host + ":" + port;
- // Canonicalise into numeric id
- const ::addrinfo& ai = getAddrInfo(*this);
-
- return asString(ai.ai_addr, ai.ai_addrlen);
-}
-
-bool SocketAddress::nextAddress() {
- bool r = currentAddrInfo->ai_next != 0;
- if (r)
- currentAddrInfo = currentAddrInfo->ai_next;
- return r;
-}
-
-void SocketAddress::setAddrInfoPort(uint16_t port) {
- if (!currentAddrInfo) return;
-
- ::addrinfo& ai = *currentAddrInfo;
- switch (ai.ai_family) {
- case AF_INET: ((::sockaddr_in*)ai.ai_addr)->sin_port = htons(port); return;
- case AF_INET6:((::sockaddr_in6*)ai.ai_addr)->sin6_port = htons(port); return;
- default: throw Exception(QPID_MSG("Unexpected socket type"));
- }
+ return host + ":" + port;
}
const ::addrinfo& getAddrInfo(const SocketAddress& sa)
{
- if (!sa.addrInfo) {
- ::addrinfo hints;
- ::memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_ADDRCONFIG; // Only use protocols that we have configured interfaces for
- hints.ai_family = AF_UNSPEC; // Allow both IPv4 and IPv6
- hints.ai_socktype = SOCK_STREAM;
-
- const char* node = 0;
- if (sa.host.empty()) {
- hints.ai_flags |= AI_PASSIVE;
- } else {
- node = sa.host.c_str();
- }
- const char* service = sa.port.empty() ? "0" : sa.port.c_str();
-
- int n = ::getaddrinfo(node, service, &hints, &sa.addrInfo);
- if (n != 0)
- throw Exception(QPID_MSG("Cannot resolve " << sa.asString(false) << ": " << ::gai_strerror(n)));
- sa.currentAddrInfo = sa.addrInfo;
- }
-
- return *sa.currentAddrInfo;
+ return *sa.addrInfo;
}
}}
diff --git a/cpp/src/qpid/sys/windows/SslAsynchIO.h b/cpp/src/qpid/sys/windows/SslAsynchIO.h
index edec081ced..3cdf2c8f08 100644
--- a/cpp/src/qpid/sys/windows/SslAsynchIO.h
+++ b/cpp/src/qpid/sys/windows/SslAsynchIO.h
@@ -39,6 +39,9 @@ namespace qpid {
namespace sys {
namespace windows {
+class Socket;
+class Poller;
+
/*
* SSL/Schannel shim between the frame-handling and AsynchIO layers.
* SslAsynchIO creates a regular AsynchIO object to handle I/O and this class
diff --git a/cpp/src/qpid/sys/windows/StrError.cpp b/cpp/src/qpid/sys/windows/StrError.cpp
index 546d399d16..9c1bfcd79c 100755
--- a/cpp/src/qpid/sys/windows/StrError.cpp
+++ b/cpp/src/qpid/sys/windows/StrError.cpp
@@ -30,7 +30,6 @@ namespace sys {
std::string strError(int err) {
const size_t bufsize = 512;
char buf[bufsize];
- buf[0] = 0;
if (0 == FormatMessage (FORMAT_MESSAGE_MAX_WIDTH_MASK
| FORMAT_MESSAGE_FROM_SYSTEM,
0,
@@ -40,11 +39,7 @@ std::string strError(int err) {
bufsize,
0))
{
-#ifdef _MSC_VER
- strerror_s(buf, bufsize, err);
-#else
- return std::string(strerror(err));
-#endif
+ strerror_s (buf, bufsize, err);
}
return std::string(buf);
}
diff --git a/cpp/src/qpid/sys/windows/Thread.cpp b/cpp/src/qpid/sys/windows/Thread.cpp
index 23b0033be4..583a9613a3 100755
--- a/cpp/src/qpid/sys/windows/Thread.cpp
+++ b/cpp/src/qpid/sys/windows/Thread.cpp
@@ -19,11 +19,6 @@
*
*/
-// Ensure definition of OpenThread in mingw
-#ifndef _WIN32_WINNT
-#define _WIN32_WINNT 0x0501
-#endif
-
#include "qpid/sys/Thread.h"
#include "qpid/sys/Runnable.h"
#include "qpid/sys/windows/check.h"
@@ -31,204 +26,50 @@
#include <process.h>
#include <windows.h>
-/*
- * This implementation distinguishes between two types of thread: Qpid
- * threads (based on qpid::sys::Runnable) and the rest. It provides a
- * join() that will not deadlock against the Windows loader lock for
- * Qpid threads.
- *
- * System thread identifiers are unique per Windows thread; thread
- * handles are not. Thread identifiers can be recycled, but keeping a
- * handle open against the thread prevents recycling as long as
- * shared_ptr references to a ThreadPrivate structure remain.
- *
- * There is a 1-1 relationship between Qpid threads and their
- * ThreadPrivate structure. Non-Qpid threads do not need to find the
- * qpidThreadDone handle, so there may be a 1-many relationship for
- * them.
- *
- * TLS storage is used for a lockless solution for static library
- * builds. The special case of LoadLibrary/FreeLibrary requires
- * additional synchronization variables and resource cleanup in
- * DllMain. _DLL marks the dynamic case.
- */
+namespace {
+unsigned __stdcall runRunnable(void* p)
+{
+ static_cast<qpid::sys::Runnable*>(p)->run();
+ _endthreadex(0);
+ return 0;
+}
+}
namespace qpid {
namespace sys {
class ThreadPrivate {
-public:
friend class Thread;
- friend unsigned __stdcall runThreadPrivate(void*);
- typedef boost::shared_ptr<ThreadPrivate> shared_ptr;
- ~ThreadPrivate();
-private:
- unsigned threadId;
HANDLE threadHandle;
- HANDLE initCompleted;
- HANDLE qpidThreadDone;
- Runnable* runnable;
- shared_ptr keepAlive;
-
- ThreadPrivate() : threadId(GetCurrentThreadId()), initCompleted(NULL),
- qpidThreadDone(NULL), runnable(NULL) {
- threadHandle = OpenThread (SYNCHRONIZE, FALSE, threadId);
- QPID_WINDOWS_CHECK_CRT_NZ(threadHandle);
- }
-
- ThreadPrivate(Runnable* r) : threadHandle(NULL), initCompleted(NULL),
- qpidThreadDone(NULL), runnable(r) {}
-
- void start(shared_ptr& p);
- static shared_ptr createThread(Runnable* r);
-};
-
-}} // namespace qpid::sys
-
-
-namespace {
-using namespace qpid::sys;
-
-#ifdef _DLL
-class ScopedCriticalSection
-{
- public:
- ScopedCriticalSection(CRITICAL_SECTION& cs) : criticalSection(cs) { EnterCriticalSection(&criticalSection); }
- ~ScopedCriticalSection() { LeaveCriticalSection(&criticalSection); }
- private:
- CRITICAL_SECTION& criticalSection;
-};
-
-CRITICAL_SECTION threadLock;
-long runningThreads = 0;
-HANDLE threadsDone;
-bool terminating = false;
-#endif
-
-
-DWORD volatile tlsIndex = TLS_OUT_OF_INDEXES;
-
-DWORD getTlsIndex() {
- if (tlsIndex != TLS_OUT_OF_INDEXES)
- return tlsIndex; // already set
-
- DWORD trialIndex = TlsAlloc();
- QPID_WINDOWS_CHECK_NOT(trialIndex, TLS_OUT_OF_INDEXES); // No OS resource
+ unsigned threadId;
- // only one thread gets to set the value
- DWORD actualIndex = (DWORD) InterlockedCompareExchange((LONG volatile *) &tlsIndex, (LONG) trialIndex, (LONG) TLS_OUT_OF_INDEXES);
- if (actualIndex == TLS_OUT_OF_INDEXES)
- return trialIndex; // we won the race
- else {
- TlsFree(trialIndex);
- return actualIndex;
+ ThreadPrivate(Runnable* runnable) {
+ uintptr_t h = _beginthreadex(0,
+ 0,
+ runRunnable,
+ runnable,
+ 0,
+ &threadId);
+ QPID_WINDOWS_CHECK_CRT_NZ(h);
+ threadHandle = reinterpret_cast<HANDLE>(h);
}
-}
-
-} // namespace
-
-namespace qpid {
-namespace sys {
-
-unsigned __stdcall runThreadPrivate(void* p)
-{
- ThreadPrivate* threadPrivate = static_cast<ThreadPrivate*>(p);
- TlsSetValue(getTlsIndex(), threadPrivate);
-
- WaitForSingleObject (threadPrivate->initCompleted, INFINITE);
- CloseHandle (threadPrivate->initCompleted);
- threadPrivate->initCompleted = NULL;
-
- try {
- threadPrivate->runnable->run();
- } catch (...) {
- // not our concern
- }
-
- SetEvent (threadPrivate->qpidThreadDone); // allow join()
- threadPrivate->keepAlive.reset(); // may run ThreadPrivate destructor
-
-#ifdef _DLL
- {
- ScopedCriticalSection l(threadLock);
- if (--runningThreads == 0)
- SetEvent(threadsDone);
- }
-#endif
- return 0;
-}
-
-
-ThreadPrivate::shared_ptr ThreadPrivate::createThread(Runnable* runnable) {
- ThreadPrivate::shared_ptr tp(new ThreadPrivate(runnable));
- tp->start(tp);
- return tp;
-}
-
-void ThreadPrivate::start(ThreadPrivate::shared_ptr& tp) {
- getTlsIndex(); // fail here if OS problem, not in new thread
-
- initCompleted = CreateEvent (NULL, TRUE, FALSE, NULL);
- QPID_WINDOWS_CHECK_CRT_NZ(initCompleted);
- qpidThreadDone = CreateEvent (NULL, TRUE, FALSE, NULL);
- QPID_WINDOWS_CHECK_CRT_NZ(qpidThreadDone);
-
-#ifdef _DLL
- {
- ScopedCriticalSection l(threadLock);
- if (terminating)
- throw qpid::Exception(QPID_MSG("creating thread after exit/FreeLibrary"));
- runningThreads++;
- }
-#endif
-
- uintptr_t h = _beginthreadex(0,
- 0,
- runThreadPrivate,
- (void *)this,
- 0,
- &threadId);
-
-#ifdef _DLL
- if (h == NULL) {
- ScopedCriticalSection l(threadLock);
- if (--runningThreads == 0)
- SetEvent(threadsDone);
- }
-#endif
-
- QPID_WINDOWS_CHECK_CRT_NZ(h);
-
- // Success
- keepAlive = tp;
- threadHandle = reinterpret_cast<HANDLE>(h);
- SetEvent (initCompleted);
-}
-
-ThreadPrivate::~ThreadPrivate() {
- if (threadHandle)
- CloseHandle (threadHandle);
- if (initCompleted)
- CloseHandle (initCompleted);
- if (qpidThreadDone)
- CloseHandle (qpidThreadDone);
-}
-
+
+ ThreadPrivate()
+ : threadHandle(GetCurrentThread()), threadId(GetCurrentThreadId()) {}
+};
Thread::Thread() {}
-Thread::Thread(Runnable* runnable) : impl(ThreadPrivate::createThread(runnable)) {}
+Thread::Thread(Runnable* runnable) : impl(new ThreadPrivate(runnable)) {}
-Thread::Thread(Runnable& runnable) : impl(ThreadPrivate::createThread(&runnable)) {}
+Thread::Thread(Runnable& runnable) : impl(new ThreadPrivate(&runnable)) {}
Thread::operator bool() {
return impl;
}
bool Thread::operator==(const Thread& t) const {
- if (!impl || !t.impl)
- return false;
return impl->threadId == t.impl->threadId;
}
@@ -238,17 +79,10 @@ bool Thread::operator!=(const Thread& t) const {
void Thread::join() {
if (impl) {
- DWORD status;
- if (impl->runnable) {
- HANDLE handles[2] = {impl->qpidThreadDone, impl->threadHandle};
- // wait for either. threadHandle not signalled if loader
- // lock held (FreeLibrary). qpidThreadDone not signalled
- // if thread terminated by exit().
- status = WaitForMultipleObjects (2, handles, false, INFINITE);
- }
- else
- status = WaitForSingleObject (impl->threadHandle, INFINITE);
+ DWORD status = WaitForSingleObject (impl->threadHandle, INFINITE);
QPID_WINDOWS_CHECK_NOT(status, WAIT_FAILED);
+ CloseHandle (impl->threadHandle);
+ impl->threadHandle = 0;
}
}
@@ -258,70 +92,9 @@ unsigned long Thread::logId() {
/* static */
Thread Thread::current() {
- ThreadPrivate* tlsValue = (ThreadPrivate *) TlsGetValue(getTlsIndex());
Thread t;
- if (tlsValue != NULL) {
- // called from within Runnable->run(), so keepAlive has positive use count
- t.impl = tlsValue->keepAlive;
- }
- else
- t.impl.reset(new ThreadPrivate());
+ t.impl.reset(new ThreadPrivate());
return t;
}
-}} // namespace qpid::sys
-
-
-#ifdef _DLL
-
-// DllMain: called possibly many times in a process lifetime if dll
-// loaded and freed repeatedly . Be mindful of Windows loader lock
-// and other DllMain restrictions.
-
-BOOL APIENTRY DllMain(HMODULE hm, DWORD reason, LPVOID reserved) {
- switch (reason) {
- case DLL_PROCESS_ATTACH:
- InitializeCriticalSection(&threadLock);
- threadsDone = CreateEvent(NULL, TRUE, FALSE, NULL);
- break;
-
- case DLL_PROCESS_DETACH:
- terminating = true;
- if (reserved != NULL) {
- // process exit(): threads are stopped arbitrarily and
- // possibly in an inconsistent state. Not even threadLock
- // can be trusted. All static destructors have been
- // called at this point and any resources this unit knows
- // about will be released as part of process tear down by
- // the OS. Accordingly, do nothing.
- return TRUE;
- }
- else {
- // FreeLibrary(): threads are still running and we are
- // encouraged to clean up to avoid leaks. Mostly we just
- // want any straggler threads to finish and notify
- // threadsDone as the last thing they do.
- while (1) {
- {
- ScopedCriticalSection l(threadLock);
- if (runningThreads == 0)
- break;
- ResetEvent(threadsDone);
- }
- WaitForSingleObject(threadsDone, INFINITE);
- }
- if (tlsIndex != TLS_OUT_OF_INDEXES)
- TlsFree(getTlsIndex());
- CloseHandle(threadsDone);
- DeleteCriticalSection(&threadLock);
- }
- break;
-
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- break;
- }
- return TRUE;
-}
-
-#endif
+}} /* qpid::sys */
diff --git a/cpp/src/qpid/sys/windows/Time.cpp b/cpp/src/qpid/sys/windows/Time.cpp
index 25c50819cd..16d09fcdc0 100644
--- a/cpp/src/qpid/sys/windows/Time.cpp
+++ b/cpp/src/qpid/sys/windows/Time.cpp
@@ -27,17 +27,6 @@
using namespace boost::posix_time;
-namespace {
-
-// High-res timing support. This will display times since program start,
-// more or less. Keep track of the start value and the conversion factor to
-// seconds.
-bool timeInitialized = false;
-LARGE_INTEGER start;
-double freq = 1.0;
-
-}
-
namespace qpid {
namespace sys {
@@ -102,35 +91,10 @@ void outputFormattedNow(std::ostream& o) {
char time_string[100];
::time( &rawtime );
-#ifdef _MSC_VER
::localtime_s(&timeinfo, &rawtime);
-#else
- timeinfo = *(::localtime(&rawtime));
-#endif
::strftime(time_string, 100,
"%Y-%m-%d %H:%M:%S",
&timeinfo);
o << time_string << " ";
}
-
-void outputHiresNow(std::ostream& o) {
- if (!timeInitialized) {
- start.QuadPart = 0;
- LARGE_INTEGER iFreq;
- iFreq.QuadPart = 1;
- QueryPerformanceCounter(&start);
- QueryPerformanceFrequency(&iFreq);
- freq = static_cast<double>(iFreq.QuadPart);
- timeInitialized = true;
- }
- LARGE_INTEGER iNow;
- iNow.QuadPart = 0;
- QueryPerformanceCounter(&iNow);
- iNow.QuadPart -= start.QuadPart;
- if (iNow.QuadPart < 0)
- iNow.QuadPart = 0;
- double now = static_cast<double>(iNow.QuadPart);
- now /= freq; // now is seconds after this
- o << std::fixed << std::setprecision(8) << std::setw(16) << std::setfill('0') << now << "s ";
-}
}}
diff --git a/cpp/src/qpid/sys/windows/mingw32_compat.h b/cpp/src/qpid/sys/windows/mingw32_compat.h
deleted file mode 100644
index 51f613cc25..0000000000
--- a/cpp/src/qpid/sys/windows/mingw32_compat.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef _sys_windows_mingw32_compat
-#define _sys_windows_mingw32_compat
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-#ifdef WIN32
-#ifndef _MSC_VER
-
-//
-// The following definitions for extension function GUIDs and signatures are taken from
-// MswSock.h in the Windows32 SDK. These rightfully belong in the mingw32 version of
-// mswsock.h, but are not included presently.
-//
-
-#define WSAID_ACCEPTEX {0xb5367df1,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}}
-typedef BOOL (PASCAL *LPFN_ACCEPTEX)(SOCKET,SOCKET,PVOID,DWORD,DWORD,DWORD,LPDWORD,LPOVERLAPPED);
-
-#endif
-#endif
-
-#endif
diff --git a/cpp/src/qpid/sys/windows/uuid.cpp b/cpp/src/qpid/sys/windows/uuid.cpp
index 3316ecbc00..b5360622dc 100644
--- a/cpp/src/qpid/sys/windows/uuid.cpp
+++ b/cpp/src/qpid/sys/windows/uuid.cpp
@@ -19,7 +19,7 @@
*
*/
-#include <rpc.h>
+#include <Rpc.h>
#ifdef uuid_t /* Done in rpcdce.h */
# undef uuid_t
#endif
@@ -52,11 +52,7 @@ int uuid_parse (const char *in, uuid_t uu) {
void uuid_unparse (const uuid_t uu, char *out) {
unsigned char *formatted;
if (UuidToString((UUID*)uu, &formatted) == RPC_S_OK) {
-#ifdef _MSC_VER
strncpy_s (out, 36+1, (char*)formatted, _TRUNCATE);
-#else
- strncpy (out, (char*)formatted, 36+1);
-#endif
RpcStringFree(&formatted);
}
}