Всем привет! У меня тоже вопрос про сервисы.
Допустим, служба создаёт Memory Mapped File - разделяемый в памяти файл.
type
PGlobalData = ^TGlobalData;
TGlobalData = packed record
...не буду грузить.
end;
var
GD: PGlobalData;
hMMF: THandle;
hMMF := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, SizeOf(TGlobalData), 'MMFServ');
if hMMF = 0 then Exit;
GD := MapViewOfFile(hMMF, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if GD = nil then Exit;
А потом обычное приложение пытается подключиться к этому файлу. Этот же самый код выдаёт ошибку "Отказано в доступе" после CreateFileMapping. Как же всё-таки получить доступ, если я Администратор компа? С SECURITY_ATTRIBUTES надо возиться? Пример не подскажете?
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
18-03-2008 22:33
2 Андрей
>>>После установки дескриптора безопасности всё и так работает как часы.
Это потому, что они в одной терминальной сессии.
А Вы попробуйте запустить пару-тройку терминальных сессий, хотя бы через FUS (на компе вне домена)
Справедливости ради я должен написать, что попробовал на WinXP SP2 Pro Corp. различные комбинации "Global\" / без "Global\" в сервисе и приложении и никакой разницы не увидел. После установки дескриптора безопасности всё и так работает как часы. И в Process Explorer-е хендлы MMF как отображались Type: Section, Name: \BaseNamedObjects\MMFServ, так и отображаются, безо всякого Global\, причём у сервиса почему-то 2 раза, у приложения 1.
Единственное различие, которое я уловил, это если в приложении будет префикс Global\, то без службы (в пользовательском режиме) оно уже работать не будет... :(
Так что пока, видимо, выгоднее оставить и в службе, и в приложении просто 'MMFServ'.
Если я сделаю так, что первым создаёт MMF не служба, а приложение, оно может тоже указать префикс Global\, а служба потом его схавает?
Префикс должны указывать обе стороны в любом случае, не зависимо от того, кто из них кто. Так что не "может", а "нужет" :-D. Только тогда нулевой DACL пусть задает приложение. В общем:
1. Нулевой DACL задает в атрибутах безопасности тот, кто объект создает (вызовом CreateFileMapping). Тот, кто открывает (OpenFileMapping) - не задает.
2. Префикс Global\ указывают обе стороны. Иначе сторона, которая его не укажет, будет будет иметь дело со своим локальным пространством имен.
Хорошо. А тогда такой вопрос. Если я сделаю так, что первым создаёт MMF не служба, а приложение, оно может тоже указать префикс Global\, а служба потом его схавает?
Этот код должен вызывать тот, кто создает объект. Тот, кто открывает существующий (OpenFileMapping), атрибуты безопасности не указывает, но префикс указать также должен. Добавление префикса нужно для того, чтобы поместить имя в глобальное пространство имен. Так как у каждой сессии пространство имен свое, и это позволяет в разных сессиях создавать разные, но одноименные объекты. А назначение нулевого DACL нужно для того, чтобы разрешить всем учеткам любой вид доступа к нему, так как по умолчанию доступ имеет только создатель - а в вашем случае создатель - это системная учетная запись, а не админ.
Нужно снабдить имя объекта префиксом Global\ и назначить нулевой DACL - обсуждалось неоднократно :)
var
sa: TSecurityAttributes;
sd: TSecurityDescriptor;
hFM: THandle;
begin
// Создаем дескриптор безопасности
InitializeSecurityDescriptor(@sd,SECURITY_DESCRIPTOR_REVISION);
// DACL не установлен - объект незащищен
SetSecurityDescriptorDacl(@sd,true,nil,false);
// Настраиваем атрибуты безопасности, передавая туда указатель на
// дескриптор безопасности sd и создаем объект
sa.nLength:=SizeOf(TSecurityAttributes);
sa.lpSecurityDescriptor:=@sd;
sa.bInheritHandle:=false;
hFM:=CreateFileMapping(hFile,@sa,PAGE_READWRITE,0,0,'Global\MyUniqueName');
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.