Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > узнать Application Data текущего пользователя


Автор: cyberovskij 5.2.2011, 21:04
Есть код:
Код

function GetActiveUserTokenF():THandle;
var pArrSessInfo      : PJwWTSSessionInfoAArray;
i:integer;
 iNumSess          : DWORD;

begin
result:=0;
if WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE,0,1,PWTS_SESSION_INFO(pArrSessInfo), iNumSess) then
   try
      for i:=0 to iNumSess-1 do
      begin
         //pArrSessInfo^[i]. .....
        if (pArrSessInfo^[i].State =WTSActive) then   
          begin
            WTSQueryUserToken(pArrSessInfo^[i].SessionId,result);
            //break;
          end;
      end //for i
      finally
        WTSFreeMemory(pArrSessInfo);
      end;

end;

////////////////////
function GetUserAppPath():string;
const
  SHGFP_TYPE_CURRENT = 0;

var
  path: array [0..MAX_PATH] of char;
  h:tHandle;
  hh:THandle;
begin
  h:=GetActiveUserTokenF();
  //hh:=THANDLE((h^));
  if h>0 then
  begin
    if SUCCEEDED(SHGetFolderPath(0,CSIDL_APPDATA,h,SHGFP_TYPE_CURRENT,@path[0])) then
      Result := path+inttostr(h)
    else
      Result := 'null';
  end
  else
  Result := 'none';
end;

///////////////////

который выполняется в системной службе в WINXP. При вызове GetUserAppPath какого то дьяволя  возвращает "C:\Documents and Settings\LocalService\Application Data" а не того пользователя, под которым сеанс?  smile 
Еще  меня смущает , то что в Дельфийской реализации  WTSQueryUserToken второй параметр имеет тип не указатель на Thandle (msdn PHANDLE) а THandle? Причем  всюду по форумах в образцах кодов все получив от функции WTSQueryUserToken указатель на токен как это описано в мсдн(PHANDLE) сразу используют его там где нужно подставлять токен(HANDLE)?

Автор: kami 5.2.2011, 22:30
http://msdn.microsoft.com/en-us/library/bb762181(v=vs.85).aspx требует TOKEN_QUERY and TOKEN_IMPERSONATE от полученного токена.
Попробуйте использовать http://msdn.microsoft.com/en-us/library/aa446616(v=vs.85).aspx с SecurityImpersonation для получения этих прав.

Добавлено через 3 минуты и 23 секунды
Цитата(cyberovskij @  5.2.2011,  21:04 Найти цитируемый пост)
в Дельфийской реализации  WTSQueryUserToken второй параметр имеет тип не указатель на Thandle (msdn PHANDLE) а THandle? 

ну так... там же 
Код

var phToken: THandle

Автор: cyberovskij 6.2.2011, 00:11
Цитата(kami @ 5.2.2011,  22:30)
Попробуйте использовать http://msdn.microsoft.com/en-us/library/aa446616(v=vs.85).aspx с SecurityImpersonation для получения этих прав.

Вот переделал. Результат тот же 
Код

function GetUserAppPath():string;//âåðòຠøëÿõ ïàïêè Application Data
const
  SHGFP_TYPE_CURRENT = 0;

var
  path: array [0..MAX_PATH] of char;
  h:tHandle;
  hh:PHandle;
begin
  WTSQueryUserToken(WTSGetActiveConsoleSessionId(),h);//GetActiveUserTokenF();
  //hh:=THANDLE((h^));
  DuplicateToken(h,SecurityImpersonation,hh);

  if h>0 then
  begin
    if SUCCEEDED(SHGetFolderPath(0,CSIDL_APPDATA,hh^,SHGFP_TYPE_CURRENT,@path[0])) then
      Result := path+inttostr(h)
    else
      Result := 'null';
  end
  else
  Result := 'none';
end;

Автор: cyberovskij 6.2.2011, 00:31
И еще я заметил что функции SHGetFolderPath вообще все равно что я пишу в третий параметр. Она всегда выдает один результат - проклатый "C:\Documents and Settings\LocalService\Application Data"

Может как то влияет то, что я использую в uses SHFolder;?

Автор: cyberovskij 6.2.2011, 01:17
Цитата(cyberovskij @ 6.2.2011,  00:31)
Может как то влияет то, что я использую в uses SHFolder;?

Точно!!! вот на странице с описанием функции в коментах написано: "If you are using the function from SHFolder.dll:Parameter hToken and dwFlags are ignored in the ANSI version of the function. They always become zero (0)."
Вопрос теперь: Откуда ее взять и как правильно импортировать?

Автор: kami 6.2.2011, 15:24
Используйте Unicodу версию smile
Изменить-то нужно всего ничего
Код

var
  path: array [0..MAX_PATH] of WideChar;
...

if SUCCEEDED(SHGetFolderPathW(...

Кстати, а какая версия Delphi?

Автор: cyberovskij 7.2.2011, 15:59
Цитата(kami @ 6.2.2011,  15:24)
Используйте Unicodу версию smile

Кстати, а какая версия Delphi?

У меня Delphi 7.
Попробовал я SHGetFolderPathW вот такой код:
Код

function GetUserAppPath():string;
const
  SHGFP_TYPE_CURRENT = 0;

var
  path: array [0..MAX_PATH] of char;
  h:tHandle;
  hh:pHandle;
  res:HRESULT;
begin
  WTSQueryUserToken(WTSGetActiveConsoleSessionId(),h);
  DuplicateToken(h,SecurityImpersonation,hh);


  if h>0 then
  begin
  
    res:=SHGetFolderPathW(0,CSIDL_APPDATA,hh^,SHGFP_TYPE_CURRENT,@path[0]);
    case res of
    S_OK:  Result := path ;
    S_FALSE:         Result := 'S_FALSE';
    E_FAIL:         Result := 'E_FAIL';
    E_INVALIDARG:         Result := 'E_INVALIDARG';
    end;

  end
  else
  Result := 'none';
end;


Выдает 'E_FAIL' - такой папки не существует smile 

Автор: kami 7.2.2011, 18:26
Цитата(cyberovskij @  7.2.2011,  15:59 Найти цитируемый пост)
У меня Delphi 7.

Аналогично.
Мой код(а вернее, Ваш smile  ) выдает "C:\Users\kami\AppData\Roaming" (у меня Vista):

Код

function TService1.GetUserAppPath(): string;
const
  SHGFP_TYPE_CURRENT = 0;
var
  path: array[0..MAX_PATH] of WideChar;
  h: tHandle;
  hh: THandle;
begin
  //CoInitialize(nil);

  //GetGlobalPrivilege('SeImpersonatePrivilege');
  //GetGlobalPrivilege('SeTcbPrivilege');

  if not WTSQueryUserToken(WTSGetActiveConsoleSessionId(), h) then
    LogMessage('WTSQueryUserToken');
  if not DuplicateToken(h, SecurityImpersonation, @hh) then
    LogMessage('DuplicateToken');

  if hh > 0 then
    begin
      LogMessage(' impersonated token = ' + IntToStr(hh));
      if SUCCEEDED(SHGetFolderPathW(0, CSIDL_APPDATA, hh, SHGFP_TYPE_CURRENT, @path[0])) then
        Result := path
      else
        Result := 'null';
    end
  else
    Result := 'none';
end;

Автор: cyberovskij 7.2.2011, 21:49
И у меня кстати мой (вернее Ваш) код выдает: C:\Documents and Settings\user2\Application Data smile 
в чем разница?
Код

function GetUserAppPath():string;
const
  SHGFP_TYPE_CURRENT = 0;

var
  path: array [0..MAX_PATH] of char;
  h:tHandle;
  hh:pHandle;
  res:HRESULT;
  //exehndl:integer;
 // hToken: Cardinal;
begin
  WTSQueryUserToken(WTSGetActiveConsoleSessionId(),h);
 // exehndl:=GetexeHandle ('explorer.exe');
  DuplicateToken(h,SecurityImpersonation,hh);
    if h>0 then
  begin
  
    res:=SHGetFolderPathW(0,CSIDL_PERSONAL,hh^,SHGFP_TYPE_CURRENT,@path[0]);
    case res of
    S_OK:  Result := path ;
    S_FALSE:         Result := 'S_FALSE';
    E_FAIL:         Result := 'E_FAIL';
    E_INVALIDARG:         Result := 'E_INVALIDARG';
    end;
  
  end
  else
  Result := 'none';
end;




А мой, ну тот что совсем мой - нет? 

Автор: CodeMonkey 7.2.2011, 22:23
Эээ, батенька.

Код
hh:PHandle;
...
DuplicateToken(h,SecurityImpersonation,hh);


Это что ещё такое? Ну и куда hh указывает? Правильно, в космос.

Автор: cyberovskij 7.2.2011, 23:14
Цитата(CodeMonkey @ 7.2.2011,  22:23)
Эээ, батенька.

Код
hh:PHandle;
...
DuplicateToken(h,SecurityImpersonation,hh);


Это что ещё такое? Ну и куда hh указывает? Правильно, в космос.

А как правильно с Phandle  работать?

Автор: CodeMonkey 8.2.2011, 10:34
В данном случае - никак. Он не нужен. 

Что такое PHandle? Указатель на THandle. По определению. На какой THandle? В вашем коде - ни на какой. Вы ж его не присвоили.

А на какой должен указывать? Ну, на тот, куда результат записывать.

Так и напишем:

Код
var
  hh: THandle;
...
DuplicateToken(h,SecurityImpersonation,@hh);


Читать http://www.transl-gunsmoker.ru/2009/09/blog-post.html.

Автор: cyberovskij 8.2.2011, 17:32
P.S. кстати с PHandle это была не единственная проблема. Кроме того кривым было еще и объявление
path: array [0..MAX_PATH] of char; а нужно было path: array[0..MAX_PATH] of WideChar; Поскольку в первом случае возвращался результат: "С" вместо нужного.

Автор: kami 8.2.2011, 19:16
Цитата(cyberovskij @  8.2.2011,  17:32 Найти цитируемый пост)
кривым было еще и объявлениеpath: array [0..MAX_PATH] of char; а нужно было path: array[0..MAX_PATH] of WideChar; 

гхм...

Цитата(kami @  6.2.2011,  15:24 Найти цитируемый пост)
Изменить-то нужно всего ничего
var
  path: array [0..MAX_PATH] of WideChar;


Автор: CodeMonkey 8.2.2011, 19:41
Ну всё, застремали человека  smile 

Автор: cyberovskij 8.2.2011, 20:45
Цитата(kami @ 8.2.2011,  19:16)
Цитата(cyberovskij @  8.2.2011,  17:32 Найти цитируемый пост)
кривым было еще и объявлениеpath: array [0..MAX_PATH] of char; а нужно было path: array[0..MAX_PATH] of WideChar; 

гхм...

Цитата(kami @  6.2.2011,  15:24 Найти цитируемый пост)
Изменить-то нужно всего ничего
var
  path: array [0..MAX_PATH] of WideChar;

ага . А это  я оказывается "открыл Америку" smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)