native/os/win32/system.c (118 lines of code) (raw):
/* 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 <winsock2.h>
#include <mswsock.h>
#include <ws2tcpip.h>
#include <tlhelp32.h>
#include "apr.h"
#include "apr_pools.h"
#include "apr_poll.h"
#include "apr_network_io.h"
#include "apr_arch_misc.h" /* for apr_os_level */
#include "tcn.h"
#include "ssl_private.h"
#pragma warning(push)
#pragma warning(disable : 4201)
#include <psapi.h>
#pragma warning(pop)
static CRITICAL_SECTION dll_critical_section; /* dll's critical section */
static HINSTANCE dll_instance = NULL;
BOOL
WINAPI
DllMain(
HINSTANCE instance,
DWORD reason,
LPVOID reserved)
{
switch (reason) {
/** The DLL is loading due to process
* initialization or a call to LoadLibrary.
*/
case DLL_PROCESS_ATTACH:
InitializeCriticalSection(&dll_critical_section);
dll_instance = instance;
break;
/** The attached process creates a new thread.
*/
case DLL_THREAD_ATTACH:
break;
/** The thread of the attached process terminates.
*/
case DLL_THREAD_DETACH:
ERR_remove_thread_state(NULL);
break;
/** DLL unload due to process termination
* or FreeLibrary.
*/
case DLL_PROCESS_DETACH:
DeleteCriticalSection(&dll_critical_section);
break;
default:
break;
}
return TRUE;
UNREFERENCED_PARAMETER(reserved);
}
static DWORD WINAPI password_thread(void *data)
{
tcn_pass_cb_t *cb = (tcn_pass_cb_t *)data;
MSG msg;
HWINSTA hwss;
HWINSTA hwsu;
HDESK hwds;
HDESK hwdu;
HWND hwnd;
/* Ensure connection to service window station and desktop, and
* save their handles.
*/
GetDesktopWindow();
hwss = GetProcessWindowStation();
hwds = GetThreadDesktop(GetCurrentThreadId());
/* Impersonate the client and connect to the User's
* window station and desktop.
*/
hwsu = OpenWindowStation("WinSta0", FALSE, MAXIMUM_ALLOWED);
if (hwsu == NULL) {
ExitThread(1);
return 1;
}
SetProcessWindowStation(hwsu);
hwdu = OpenDesktop("Default", 0, FALSE, MAXIMUM_ALLOWED);
if (hwdu == NULL) {
SetProcessWindowStation(hwss);
CloseWindowStation(hwsu);
ExitThread(1);
return 1;
}
SetThreadDesktop(hwdu);
hwnd = CreateDialog(dll_instance, MAKEINTRESOURCE(1001), NULL, NULL);
if (hwnd != NULL)
ShowWindow(hwnd, SW_SHOW);
else {
ExitThread(1);
return 1;
}
while (1) {
if (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE)) {
if (msg.message == WM_KEYUP) {
int nVirtKey = (int)msg.wParam;
if (nVirtKey == VK_ESCAPE) {
DestroyWindow(hwnd);
break;
}
else if (nVirtKey == VK_RETURN) {
HWND he = GetDlgItem(hwnd, 1002);
if (he) {
int n = GetWindowText(he, cb->password, SSL_MAX_PASSWORD_LEN - 1);
cb->password[n] = '\0';
}
DestroyWindow(hwnd);
break;
}
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
Sleep(100);
}
/* Restore window station and desktop.
*/
SetThreadDesktop(hwds);
SetProcessWindowStation(hwss);
CloseDesktop(hwdu);
CloseWindowStation(hwsu);
ExitThread(0);
return 0;
}
int WIN32_SSL_password_prompt(tcn_pass_cb_t *data)
{
DWORD id;
HANDLE thread;
/* TODO: See how to display this from service mode */
thread = CreateThread(NULL, 0,
password_thread, data,
0, &id);
WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
return (int)strlen(data->password);
}