Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Службы и GDI, Проблема создания скриншотов 
:(
    Опции темы
altom
Дата 29.11.2013, 15:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 29.11.2013

Репутация: нет
Всего: нет



Приветствую всех.
Есть 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. Что может мешать получению скриншота с экрана приветствия?
PM MAIL   Вверх
Dik0n
Дата 29.11.2013, 15:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 153
Регистрация: 11.5.2011

Репутация: 1
Всего: 10



На ХР точно работает (процесс запускается от мени пользователя) на 7ке не проверял.
Код

// Получаем ID сессии в рамках которой
// ведет работу залогиненый пользователь
SessionID = WTSGetActiveConsoleSessionId;
// Получаем токен пользователя
WTSQueryUserToken(SessionID, hInteractiveToken);

si.lpDesktop = "Winsta0\Default";
CreateProcessAsUser(hInteractiveToken, ...)

--------------------
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ◄◄◄ Сотри монеткой защитный слой
PM MAIL WWW   Вверх
xvr
Дата 2.12.2013, 09:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 40
Всего: 223



Начиная с Windows Vista все сервисы запускаются под своей собственной Window Station со своим собственным Desktop'ом, и изменить это вы не сможете. Более того, открыть любую пользовательскую сессию (Windows Station) от имени сервиса (LOCAL SYSTEM) вы тоже не сможете.
Выход - запускать процесс от имени конкретного пользователя и на его Window Station. См функцию CreateProcessWithLogonW (и не забудьте заполнить lpStartupInfo->lpDesktop)

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.1056 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.