Всех приветствую.
Есть Windows служба:
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
if(!hSCManager) {
return false;
}
GetModuleFileName(NULL, servicePath, MAX_PATH);
DWORD wver = LOWORD(GetVersion());
wver = (LOBYTE(wver) << 8) + HIBYTE(wver);
DWORD stype = SERVICE_WIN32_OWN_PROCESS;
if (wver < 0x0600) {
stype |= SERVICE_INTERACTIVE_PROCESS;
}
SC_HANDLE hService = CreateService(
hSCManager,
serviceName,
serviceName,
SERVICE_ALL_ACCESS,
stype,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
servicePath,
NULL, NULL, NULL, NULL, NULL
);
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
Служба запускает другой процесс:
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
memset(&pi, 0, sizeof(pi));
HANDLE proc = GetCurrentProcess();
HANDLE cur_token, new_token;
DWORD session = WTSGetActiveConsoleSessionId();
if (!OpenProcessToken(proc, TOKEN_DUPLICATE, &cur_token)) {
return false;
}
if (!DuplicateTokenEx(cur_token, TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, &new_token)) {
return false;
}
if (!SetTokenInformation(new_token, (TOKEN_INFORMATION_CLASS) TokenSessionId, &session, sizeof(session))) {
return false;
}
CreateProcessAsUser(new_token, NULL, "program.exe scr", NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
CloseHandle(token);
CloseHandle(userToken);
Этот процесс занимается снятием скриншотов:
HDC winDC = CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
HDC bmpDC = CreateCompatibleDC(winDC);
int width = GetDeviceCaps(winDC, HORZRES);
int height = GetDeviceCaps(winDC, VERTRES);
BITMAPINFOHEADER bmpInfoHeader;
BITMAPFILEHEADER bmpFileHeader;
bmpFileHeader.bfType = 0x4d42;
bmpFileHeader.bfSize = 0;
bmpFileHeader.bfReserved1 = 0;
bmpFileHeader.bfReserved2 = 0;
bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmpInfoHeader.biSize = sizeof(bmpInfoHeader);
bmpInfoHeader.biWidth = width;
bmpInfoHeader.biHeight = height;
bmpInfoHeader.biPlanes = 1;
bmpInfoHeader.biBitCount = 24;
bmpInfoHeader.biCompression = BI_RGB;
bmpInfoHeader.biSizeImage = width * height * 3;
bmpInfoHeader.biXPelsPerMeter = 0;
bmpInfoHeader.biYPelsPerMeter = 0;
bmpInfoHeader.biClrUsed = 0;
bmpInfoHeader.biClrImportant = 0;
BITMAPINFO info;
info.bmiHeader = bmpInfoHeader;
void* memory;
HBITMAP bitmap;
bitmap = CreateDIBSection(winDC, &info, DIB_RGB_COLORS, &memory, NULL, 0);
SelectObject(bmpDC, bitmap);
if (!BitBlt(bmpDC, 0, 0, width, height, winDC, 0, 0, SRCCOPY | CAPTUREBLT)) {
return false;
}
FILE *f = fopen("scrsht.bmp", "wb");
fwrite(&bmpFileHeader, 1, sizeof(BITMAPFILEHEADER), f);
fwrite(&bmpInfoHeader, 1, sizeof(BITMAPINFOHEADER), f);
fwrite(memory, 1, bmpInfoHeader.biSizeImage, f);
fclose(f);
Проблема заключается в том, что при работе под Windows XP приходится делать службу интерактивной
(иначе на скриншоте получаем черный прямоугольник), а интерактивные службы могут быть запрещены на машине клиента.
Но, коль скоро скриншоты делает не служба, а запущенный процесс, напрашивается вывод о том, что процесс
наследует какие-то права службы, которые мешают ему получить доступ к консоли.
При этом, даже в случае интерактивной службы, при отображении экрана приветствия получается черный прямоугольник.
По некоторым причинам служба и дочерний процесс представлены одним exe файлом, но непосредственно функционал
(запуск дочернего процесса и снятие скриншотов) расположен в dll (общей). Было сомнение по поводу того, что
проблема может быть связана с загрузкой этой dll из сервиса и последующим использованием ее же в дочернем
процессе, но разнесение функционала по разным dll не помогло.
Возможно, я не стал бы биться над решением этой задачи, списал бы это на ограничения винды, если бы не TightVNC,
которая производит аналогичные манипуляции, при этом не регистрируя сервис как интерактивный.
Собственно, отсюда 2 вопроса:
1. Какие права нужно добавить/отобрать у процесса, чтобы его работа не зависела от настроек службы (если проблема в правах)?
2. Что может мешать получению скриншота с экрана приветствия?