Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2009.04.05;
Скачать: [xml.tar.bz2];

Вниз

Узнать хендлы открытых процессом файлов   Найти похожие ветки 

 
Виталий   (2008-04-10 14:57) [0]

Уважаемые мастера, подскажите пожалуйста как по номеру процесса получить хендлы и пути файлов, которые он открыл?
Если можно скажите какая последовательность вызовов функций  должна быть и какие точно функции для этого нужны

Заранее спасибо.


 
Виталий   (2008-04-10 14:57) [1]

О еще, может процессы где то в себе держат этот список, как его получить?


 
Сергей М. ©   (2008-04-10 15:12) [2]

И что ты с ними намерен делать ?

Ты их потерял что ли ?)


 
Виталий   (2008-04-10 15:43) [3]

Я хочу программно получить путь к файлу который открыт в Ворде.
Я запускаю свою программу нахожу процесс WinWord и хочу увидеть какой файл(ы) он открыл


 
Виталий   (2008-04-10 15:43) [4]

Это для сбора информации кто какой пользователь с чем работает


 
Сергей М. ©   (2008-04-10 16:14) [5]

Ты в курсе, что WinWord являет собой полноценный сервер OLE-автоматизации, (который способен сам сообщить о файлах, с которыми он работает, если его об этом спросят на его языке) ?

Или ты про такую слыхом не слыхивал ?


 
Виталий   (2008-04-10 16:36) [6]

В курсе, только мне не только ВинОфис нужно отлавливать а любую программу, окно которой активно в данный момент. Ворд это я к примеру.
Ладно Ворд не нравится, возьмем Сполайт. Он то не сообщит о себе.

Ты лучше скажи знаеш как это делать или как всегда в гугль идти?


 
Сергей М. ©   (2008-04-10 16:40) [7]

Ну раз ты на ходу меняешь формулировку задачи, то как всегда)


 
Riply ©   (2008-04-10 17:21) [8]

> [0] Виталий   (10.04.08 14:57)
> подскажите пожалуйста как по номеру процесса получить хендлы и пути файлов, которые он открыл?

Попробуй с помощью следующих функций:

NtQuerySystemInformation(..,SystemHandleInformation,..)
DuplicateHandle
NtQueryObject

P.S.
Возможно, вместо NtQuerySystemInformation, можно использовать NtQueryInformationProcess для конкретного процесса.
Не знаю, надо смотреть.


 
Riply ©   (2008-04-10 17:22) [9]

>  [8] Riply ©   (10.04.08 17:21)

P.P.S.
Будь осторожен с Pipe -ми :)


 
slow!alfamoon!com   (2008-04-10 18:14) [10]

Riply: вроде проблема с пайпами в сп2 решилась, или я неправильно помню?
Автор: http://slow.alfamoon.com/?module=filesdb&id=1&fid=12&get=1 только тут про сокеты, это тоже файлы, и для всех процессов, так что добавишь фильтрацию по PID нужного процесса


 
Riply ©   (2008-04-10 22:04) [11]

> [10] slow!alfamoon!com   (10.04.08 18:14)
> Riply: вроде проблема с пайпами в сп2 решилась, или я неправильно помню?

Давно это было, но до сих пор пайповая проблемма сидит у меня в голове с меткой "не решенная" :)
Напомни, пожалуйста, на основании чего ты считаешь, что она решилась ?


 
Виталий   (2008-04-11 12:47) [12]

Riply, slow!alfamoon!com - Спасибо за примеры. хоть кто-то не издевается, оказывается есть еще тут нормальные люди.

Собсно почитал МС-Рема и Багеля, и решил проблему. Кстати Пайпы меня не интересуют, только физические файлы.


 
Rouse_ ©   (2008-04-11 15:50) [13]

С пайпами проблема не решилась :) Как висели так и висят :) Надо просто уметь их идентифицировать :)


 
slow!alfamoon!com   (2008-04-11 15:57) [14]


> Напомни, пожалуйста, на основании чего ты считаешь, что
> она решилась ?
>

в каком-то обсуждении на wasm.ru вроде пробегало, надо посмотреть будет.


 
Riply ©   (2008-04-11 16:34) [15]

> [13] Rouse_ ©   (11.04.08 15:50)
> С пайпами проблема не решилась :) Как висели так и висят :) Надо просто уметь их идентифицировать :)

Сколько не билась над их идентификацией (имея на руках только информацию от NtQuerySystemInformation), ничего у меня не вышло :(.
На самом незначительном запросе - висла.
Саш, подскажи как надо делать.


 
slow!alfamoon!com   (2008-04-11 16:36) [16]

2 Riply собственно вариант решения это запрос в отдельном потоке, был предложен еще давно и ничего нового не придумано


 
Riply ©   (2008-04-11 16:42) [17]

> [16] slow!alfamoon!com   (11.04.08 16:36)
> 2 Riply собственно вариант решения это запрос в отдельном потоке,
> был предложен еще давно и ничего нового не придумано

Терминирование нити ?
Я не считаю это за "вариант решения". IMHO, так некузяво, что дальше некуда :)
Кто-то из форумчан хорошо по этому поводу сказал: "Ведь по живому режешь".
Я с ним согласна :)


 
Rouse_ ©   (2008-04-11 16:46) [18]


> Riply ©   (11.04.08 16:34) [15]

Т.к. нужно искать только файловые хэндлы, то перед вызовом NtQueryObject нужно сказать NtQueryInformationFile и проверить результат, если STATUS_SUCCESS, то повиснуть не должны ;)
Т.е. что-то вроде этого:

 function GetFileNameThread(lpParameters: Pointer): DWORD; stdcall;
 var
   FileNameInfo: FILE_NAME_INFORMATION;
   ObjectNameInfo: TOBJECT_NAME_INFORMATION;
   IoStatusBlock: IO_STATUS_BLOCK;
   pThreadParam: TGetFileNameThreadParam;
   dwReturn: DWORD;
 begin
   ZeroMemory(@FileNameInfo, SizeOf(FILE_NAME_INFORMATION));
   pThreadParam := PGetFileNameThreadParam(lpParameters)^;
   Result := NtQueryInformationFile(pThreadParam.hFile, @IoStatusBlock,
     @FileNameInfo, MAX_PATH * 2, FileNameInformation);
   if Result = STATUS_SUCCESS then
   begin
     Result := NtQueryObject(pThreadParam.hFile, ObjectNameInformation,
       @ObjectNameInfo, MAX_PATH * 2, @dwReturn);
     if Result = STATUS_SUCCESS then
     begin
       pThreadParam.Status := Result;
       WideCharToMultiByte(CP_ACP, 0,
         @ObjectNameInfo.Name.Buffer[ObjectNameInfo.Name.MaximumLength -
         ObjectNameInfo.Name.Length],
         ObjectNameInfo.Name.Length, @pThreadParam.Data[0],
         MAX_PATH, nil, nil);
     end
     else
     begin
       pThreadParam.Status := STATUS_SUCCESS;
       Result := STATUS_SUCCESS;
       WideCharToMultiByte(CP_ACP, 0,
         @FileNameInfo.FileName[0], IoStatusBlock.Information,
         @pThreadParam.Data[0],
         MAX_PATH, nil, nil);
     end;
   end;
   PGetFileNameThreadParam(lpParameters)^ := pThreadParam;
   ExitThread(Result);
 end;

 function GetFileNameFromHandle(hFile: THandle): String;
 var
   lpExitCode: DWORD;
   pThreadParam: TGetFileNameThreadParam;
   hThread: THandle;
 begin
   Result := "";
   ZeroMemory(@pThreadParam, SizeOf(TGetFileNameThreadParam));
   pThreadParam.hFile := hFile;
   hThread := CreateThread(nil, 0, @GetFileNameThread, @pThreadParam, 0, PDWORD(nil)^);
   if hThread <> 0 then
   try
     case WaitForSingleObject(hThread, 100) of
       WAIT_OBJECT_0:
       begin
         GetExitCodeThread(hThread, lpExitCode);
         if lpExitCode = STATUS_SUCCESS then
           Result := pThreadParam.Data;
       end;
       WAIT_TIMEOUT:
         TerminateThread(hThread, 0);
     end;
   finally
     CloseHandle(hThread);
   end;
 end;


Я ж тебе помоемому давал уже этот код...


 
slow!alfamoon!com   (2008-04-11 17:02) [19]

2 Rouse_
NtQueryObject тоже виснет. На wasm.ru обсуждали

http://www.wasm.ru/forum/viewtopic.php?id=7728


 
Rouse_ ©   (2008-04-11 17:04) [20]

Ну не знаю... У меня этот код отрабатывает четко, ни одного срыва потока нет, хоть код и оставлен на всякий случай... Если без NtQueryInformationFile тогда виснет...


 
Rouse_ ©   (2008-04-11 17:07) [21]

А, ну понятно, там запрашивается FileModeInformation, а я прошу FileNameInformation :)


 
Riply ©   (2008-04-11 17:07) [22]

> [18] Rouse_ ©   (11.04.08 16:46)

> Т.к. нужно искать только файловые хэндлы, то перед вызовом NtQueryObject нужно сказать
> NtQueryInformationFile и проверить результат, если STATUS_SUCCESS, то повиснуть не должны ;)

Саш, насколько я помню, на самом запросе NtQueryInformationFile мы виснем с не меньшим успехом,
просто зависание не такое "глубокое" :)
Но нить терминировать все равно приходиться.
Могу еще раз проверить, если ошибаюсь.

P.S.
Кто-то говорил, что решил данную проблемму "путем анализа таблицы Handle`ов"
или что-то в этом духе. Не помню. Поиск по архивам старых веток ничего не дал.


 
Rouse_ ©   (2008-04-11 17:08) [23]

Проверь...


 
Riply ©   (2008-04-11 17:09) [24]

> [21] Rouse_ ©   (11.04.08 17:07)
> А, ну понятно, там запрашивается FileModeInformation, а я прошу FileNameInformation :)

Так. Бросаю все дела и иду проверять :)


 
Riply ©   (2008-04-11 17:10) [25]

>  [24] Riply ©   (11.04.08 17:09)

P.S.
Надеюсь что много времени это не займет :)


 
Rouse_ ©   (2008-04-11 17:26) [26]

Код у меня на сайте в разделе WinAPI возьми, чтоб самой не собирать...


 
Rouse_ ©   (2008-04-11 17:40) [27]

я сейчас изменил свой код на вот такой:

       WAIT_TIMEOUT:
       begin
         TerminateThread(hThread, 0);
         Result := "Thread terminated";
       end;


сработок не было :)


 
Riply ©   (2008-04-11 17:41) [28]

>  [26] Rouse_ ©   (11.04.08 17:26)
> Код у меня на сайте в разделе WinAPI возьми, чтоб самой не собирать...

Хорошо.

Пока протестила у себя (на своем коде).
Добавила проверку NtQueryInformationFile(FileNameInformation).
Не помогло:
Если пробегаться по всем процессам системы, то терминировать нить приходится 25-26 раз.

Сейчас скачаю оригинальный код и попробую тоже самое с ним.


 
Rouse_ ©   (2008-04-11 17:48) [29]

обманул я тебя :) действительно приходится срывать... оть-же... Не обращал на этот момент внимание... Там у меня логика работы, что ищется процесс и путь к файлу, если не находит - в лог ничего не выводиться... Блин... Лан будем думать...


 
Riply ©   (2008-04-11 18:00) [30]

> [29] Rouse_ ©   (11.04.08 17:48)
> обманул я тебя :)

А я уж было стала готовить отчет: чем твой пример компилировался, да на какой системе тестировался :)

> Лан будем думать...

Повторюсь: к сожалению, не помню кто с нашего форума (из мастеров)
говорил что решил проблемму "путем анализа таблицы Handle`ов". Или что-то в таком духе.


 
Riply ©   (2008-04-12 04:50) [31]

Вот ведь надо же было напоминать об этой проблемме.
Вместо того чтобы делом заниматься, Handl`ы тут перечисляю :)

Если кому интересно вот некоторые результаты:
Как я уже говорила, давным-давно пыталась найти хоть какой-то запрос,
на котором не виснем, и по результату (или по возвращаемой ошибке) которого
можно было бы хотя бы разбить объекты типа файл на две группы:
"Опасную" и "Безопасную".

В этом случае, для "Опасной" группы, если уж так приспичило создаем нить,
а с другой работаем "напрямую".

Меня постигла неудача - самые невинные запросы приводили к зависанию.
Сейчас я подумала, а может попробовать в запросе не напрямую,
а как-то косвенно обратиться к Handl`у ?
И вот что у меня получилось:

По аналогии с методикой, используемой в ReopenFile (подсказанной guav - ом),
попробуем запросить атрибуты у файла с пустым именем,
указав в качестве его родителя наш "подопытный" Handle.
Т.е. делаем вид, что он нас вовсе не интересует, а интересует только ребенок :)

var
EmptyName: UNICODE_STRING;
BaseInfo: FILE_BASIC_INFORMATION;
ObjectAttr: OBJECT_ATTRIBUTES;
begin
RtlInitUnicodeString(@EmptyName, nil);
InitializeObjectAttributes(@ObjectAttr, @EmptyName, OBJ_CASE_INSENSITIVE, pThreadParam.hFile, nil);
Result := NtQueryAttributesFile(@ObjectAttr, @BaseInfo);


Если Result = STATUS_SUCCESS, то (в зависимости от типа теста)
обходимся без нити, либо внутри нити не делаем запросы, ведущие к зависанию.

Результаты при пробежке по всем процессам системы:
RequestCount          1248 // Всего запросов для объектов типа FILE
SuccessRequestCount    801 // из них успешных
ErrorRequestCount      447 // и с ошибкой. Здесь, кроме файлов в стандартном понимании, еще куча всего :)

Итого в двух случаях из трех можно обойтись без нити.
И только треть остается под вопросом.
(Выигрыш по времени в разы :)

Тестирование на коде от Rouse дало более интересные результаты:
(У себя я шла по всем объектам без исключений и какой либо фильтрации )

Исходный код без изменений:
---------------------------
NameCount:  433
TickCount:  15015
TerminateCount:  25

Запрос нити для всех объектов, но внутри нити предварительная проверка на NtQueryAttributesFile
---------------------------
NameCount:  429
TickCount:  6000
TerminateCount:  0

Работаем вообще без нитей, основываясь на показаниях NtQueryAttributesFile :)
---------------------------
NameCount:  429
TickCount:  937
TerminateCount:  0

В последнем случае выигыш уже не в разы а на порядки, уж не говоря о "нерезаньи по-живому" :)

Есть маленькая неувязочка.
Мы потеряли четыре файла.
Кто они такие (может нормальные пайпы или еще кто) и почему потерялись,
оставляю изучение этого вопроса заинтересованным лицам. :)
Как подсказку к разбирательствам могу дать следующее:
я отбрасывала запрос на имя не анализируя результат.
Т.е если Result <> STATUS_SUCCESS, то бросала это дело.
На самом деле анализ может что-то подсказать.
Возвращаемые ошибки, которые удалось засечь:
STATUS_UNSUCCESSFUL, STATUS_INVALID_DEVICE_REQUEST, STATUS_INVALID_PARAMETER,
STATUS_OBJECT_NAME_INVALID, STATUS_OBJECT_NAME_NOT_FOUND, STATUS_NOT_SUPPORTED

Ну и напоследок приведу основные изменения Сашином коде,
которые надо сделать для тестирования описанного выше безобразия:

function GetFileNameDirect(hFile: THandle; var FileName: string): NTSTATUS; // - integer !!!
var
ObjectNameInfo: TOBJECT_NAME_INFORMATION;
dwReturn: DWORD;
// !!!! Это другое определение UNICODE_STRING, не как у Саши в данном примере
EmptyName: UNICODE_STRING;
BaseInfo: FILE_BASIC_INFORMATION;
ObjectAttr: OBJECT_ATTRIBUTES;
begin
 FileName := "";
 RtlInitUnicodeString(@EmptyName, nil);
 InitializeObjectAttributes(@ObjectAttr, @EmptyName, OBJ_CASE_INSENSITIVE, hFile, nil);
 Result := NtQueryAttributesFile(@ObjectAttr, @BaseInfo);
 if Result = STATUS_SUCCESS then
  begin
   Result := NtQueryObject(hFile, ObjectNameInformation,
                           @ObjectNameInfo, MAX_PATH * 2, @dwReturn);
   if Result = STATUS_SUCCESS then
    begin
     SetLength(FileName, MAX_PATH);
     WideCharToMultiByte(CP_ACP, 0, @ObjectNameInfo.Name.Buffer[ObjectNameInfo.Name.MaximumLength -
         ObjectNameInfo.Name.Length], ObjectNameInfo.Name.Length, PChar(FileName),
         MAX_PATH, nil, nil);
    end
  end;
end;


Чуть измененная GetFileNameThread:

function GetFileNameThread(lpParameters: Pointer): DWORD; stdcall;
var
FileNameInfo: FILE_NAME_INFORMATION;
ObjectNameInfo: TOBJECT_NAME_INFORMATION;
IoStatusBlock: IO_STATUS_BLOCK;
pThreadParam: TGetFileNameThreadParam;
dwReturn: DWORD;
// !!!! Это другое определение UNICODE_STRING, не как у Саши в данном примере
EmptyName: UNICODE_STRING;
BaseInfo: FILE_BASIC_INFORMATION;
ObjectAttr: OBJECT_ATTRIBUTES;
begin
ZeroMemory(@FileNameInfo, SizeOf(FILE_NAME_INFORMATION));
pThreadParam := PGetFileNameThreadParam(lpParameters)^;

// RtlInitUnicodeString(@EmptyName, nil);
// InitializeObjectAttributes(@ObjectAttr, @EmptyName, OBJ_CASE_INSENSITIVE, pThreadParam.hFile, nil);
// Result := NtQueryAttributesFile(@ObjectAttr, @BaseInfo);
   Result := STATUS_SUCCESS;// Для теста внутри нити закоментировать эту строчку и открыть предыдущие

 if Result = STATUS_SUCCESS then
  begin
   // Не убирайте эту строчку - на ней зависание не такое "глубокое"  :)
   if GetFileType(pThreadParam.hFile) <> FILE_TYPE_PIPE
    then Result := NtQueryInformationFile(pThreadParam.hFile, @IoStatusBlock,
                                    @FileNameInfo, MAX_PATH * 2, FileNameInformation);

   if Result = STATUS_SUCCESS then
    begin
     Result := NtQueryObject(pThreadParam.hFile, ObjectNameInformation,
                             @ObjectNameInfo, MAX_PATH * 2, @dwReturn);
     if Result = STATUS_SUCCESS then
      begin
       pThreadParam.Status := Result;
       WideCharToMultiByte(CP_ACP, 0,
         @ObjectNameInfo.Name.Buffer[ObjectNameInfo.Name.MaximumLength -
         ObjectNameInfo.Name.Length],
         ObjectNameInfo.Name.Length, @pThreadParam.Data[0],
         MAX_PATH, nil, nil);
      end
     else
      begin
       pThreadParam.Status := STATUS_SUCCESS;
       Result := STATUS_SUCCESS;
       WideCharToMultiByte(CP_ACP, 0,
         @FileNameInfo.FileName[0], IoStatusBlock.Information,
         @pThreadParam.Data[0],
         MAX_PATH, nil, nil);
      end;
    end;
  end;

 PGetFileNameThreadParam(lpParameters)^ := pThreadParam;
 ExitThread(Result);
end;


Изменения в главной процедуре:
if GetFileNameDirect(hFile, FilePath) <> STATUS_SUCCESS
then ;//FilePath := GetFileNameFromHandle(hFile);


Уфф... Вроде все.

В заключении хочу сказать, что то что у меня не нашлось объектов,
на которых NtQueryAttributesFile ведет к зависанию, вовсе не означает,
что их не существует :)


 
Игорь Шевченко ©   (2008-04-12 12:03) [32]

Riply ©   (12.04.08 04:50) [31]

Можно нескромный вопрос - а нафига такие извращения ?
Все равно ты не получишь со 100% гарантией список открытых файлов (хендлов) чужого (да и своего тоже) процесса, к чему мучиться ?

Я просто к чему - сам страдал в свое время ерундой, потом сообразил, что лучше самодвижущееся пресс-папье изобрести.

Кому надо узнать список открытых хендлов, нехай запустит handles.exe или Process Explorer, авторы этих инструментов известны, а главное, применяют в корне другой подход.

И это правильно.


 
Riply ©   (2008-04-12 17:07) [33]

> [32] Игорь Шевченко ©   (12.04.08 12:03)
> Все равно ты не получишь со 100% гарантией список открытых файлов (хендлов) чужого (да и своего тоже) процесса, к чему мучиться ?

Когда FileExists возвращает False это не означает что файл не существует, imho. Зачем она нужна ? :)

> Можно нескромный вопрос - а нафига такие извращения ?

Вопрос скромный :)
Начнем с того, что свой блок для работы с Handl`ми (не обязательно "файловыми") я написала только для
себя и не собираюсь его предлагать другим.
Не потому что жадная, а потому что нехай запустит "handles.exe или Process Explorer". :)
Мой блок работает так как надо мне и умеет то, что нужно мне.
А чтобы что-то работало так как надо ее величеству Riply, может написать только Riply :)
И он мне в работе неоднократно помогал в работе.  
Это раз.

Второе:
мне очень не нравиться, когда у меня за спиной висят нерешенные задачи.
А я люблю себя чуствовать комфортно. :)

Третье:
этот вопрос интересует многих и мне будет приятно, если мое решение окажется правильным и принесет кому-то пользу :)

Четвертое:
Во время "страдания ерундой" я лучше начинаю понимать (чуствовать) как работает система
и получаю новые знания.


Есть еще пятое, шестое и т.д. Если будет интересно, продолжу перечисление :)

Вот так и получается, Игорь, что все это я делала для себя любимой :)


 
Riply ©   (2008-04-12 17:10) [34]

> [33] Riply ©   (12.04.08 17:07)

Нулевой пункт забыла:

Мне интересно !  :)


 
Игорь Шевченко ©   (2008-04-12 23:52) [35]

Riply ©   (12.04.08 17:07) [33]

Я к чему - и Process Explorer и handles.exe используют для получения информации ядерный драйвер.

Как ты понимаешь, и Руссиновичу и брату его во Христе Когсуэллу тоже интересно "как это там система работает", весьма вероятно, что было интересно даже больше, чем тебе. Следовательно, они пришли к выводу, что попытки получить такую информацию из пользовательского режима рано или поздно закончатся неудачей. Вот и Шрайбер тоже рекомендует для получения информации пользоваться драйвером - у него, у драйвера, возможностей больше - можно читать напрямую те же таблицы, из которых получается информация, возвращаемая NtQueryxxxxx, и главное, что в это время тебе никто не мешает. А от вызова NtQueryxxxx до вызова NtQueryzzzz в системе может произойти масса событий, в результате чего информация собранная обоими вызовами будет настолько не соответствовать действительности, что потеряет всякий смысл.


 
Riply ©   (2008-04-13 00:54) [36]

> [35] Игорь Шевченко ©   (12.04.08 23:52)

Вынуждена полностью согласиться со всеми утверждениями.
К сожалению, до написания драйвера я еще не доросла. Уровень не тот :(
Правда, "еще не вечер" :)

А пока идет обучение, вынуждена довольствоваться тем,
что удается получить в пользовательском режиме :)


 
Игорь Шевченко ©   (2008-04-13 00:59) [37]


> К сожалению, до написания драйвера я еще не доросла. Уровень
> не тот :(


Да это несложно. Покупается/ищется книга Свена Шрайбера "Недокументированные возможности Windows 2000" - там как раз таких драйверов, которые читают ядерные таблицы, штук несколько, и по шагам расписано их написание. Я серьезно.


 
Riply ©   (2008-04-13 01:22) [38]

> [37] Игорь Шевченко ©   (13.04.08 00:59)
> Да это несложно. Покупается/ищется книга Свена Шрайбера "Недокументированные возможности Windows 2000" -
> там как раз таких драйверов, которые читают ядерные таблицы, штук несколько, и по шагам расписано их написание.
> Я серьезно.

Ой, Игорь, я ведь могу последовать совету и сунуться в эту область :)
И дорги назад уже не будет. Уж я то себя знаю. Так и завязну там :)



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2009.04.05;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.58 MB
Время: 0.006 c
2-1234453501
Oleg_teacher
2009-02-12 18:45
2009.04.05
Серийный номер мат. платы


2-1234773241
Andrewtitoff
2009-02-16 11:34
2009.04.05
Word Отступ слева


15-1232570914
Cyrax
2009-01-21 23:48
2009.04.05
Чем отличаются Nokia N95, Nokia N95 1 year navigation...


15-1233732052
KSergey
2009-02-04 10:20
2009.04.05
Изменения в законе об авторском праве


3-1217676103
VadimSpb
2008-08-02 15:21
2009.04.05
Символ # в имени таблицы





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский