-
Здравствуйте.
СИТУАЦИЯ Я использую именованные мьютексы для запрета запуска более одного приложения из группы. Т.е. есть 6 приложений и один сервис, и только один из них может быть запущен в один момент времени. При создании мьютекса я передаю NIL в первом параметре функции CreateMutex.
ПРОБЛЕМЫ Если первым запускается сервис он создается именованный мьютекс. При этом при запуске обычного приложения и попытке создания мьютекса с аналогичным именем происходит ошибка - недостаточно прав.
Я так понимаю, что это потому, что сервис работает из под LocalSystem. И мьютекс имеет по умолчанию права этого самого LocalSystem. И обычное приложение доступа к мьютексу не имеет.
ВОПРОСЫ 1. Как задать первый параметр в CreateMutex таким образом, чтобы любой эккаунт мог выполнить CreateMutex без ошибки недостаточности прав? 2. Как поведет себя Win98, если в нем выполнить CreateMutex с заданием прав?
Спасибо.
-
RTFM: SecurityDescriptor
где-то так...
function CreateFullAccessSA(var SA: TSecurityAttributes): Boolean; type TAceHeader = packed record AceType: Byte; AceFlags: Byte; AceSize: Word; end; TAccessAllowedAce = packed record Header: TAceHeader; Mask: ACCESS_MASK; SidStart: DWORD; end; const FILE_READ_DATA = $0001; // file & pipe FILE_LIST_DIRECTORY = $0001; // directory FILE_WRITE_DATA = $0002; // file & pipe FILE_ADD_FILE = $0002; // directory FILE_APPEND_DATA = $0004; // file FILE_ADD_SUBDIRECTORY = $0004; // directory FILE_CREATE_PIPE_INSTANCE = $0004; // named pipe FILE_READ_EA = $0008; // file & directory FILE_WRITE_EA = $0010; // file & directory FILE_EXECUTE = $0020; // file FILE_TRAVERSE = $0020; // directory FILE_DELETE_CHILD = $0040; // directory FILE_READ_ATTRIBUTES = $0080; // all FILE_WRITE_ATTRIBUTES = $0100; // all FILE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED or Windows.SYNCHRONIZE or $1FF); FILE_GENERIC_READ = (STANDARD_RIGHTS_READ or FILE_READ_DATA or FILE_READ_ATTRIBUTES or FILE_READ_EA or Windows.SYNCHRONIZE); FILE_GENERIC_WRITE = (STANDARD_RIGHTS_WRITE or FILE_WRITE_DATA or FILE_WRITE_ATTRIBUTES or FILE_WRITE_EA or FILE_APPEND_DATA or Windows.SYNCHRONIZE); FILE_GENERIC_EXECUTE = (STANDARD_RIGHTS_EXECUTE or FILE_READ_ATTRIBUTES or FILE_EXECUTE or Windows.SYNCHRONIZE);
HEAP_ZERO_MEMORY = $00000008; ACL_REVISION = 2; SECURITY_WORLD_RID = $00000000; SECURITY_WORLD_SID_AUTHORITY: TSidIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 1)); var pSD: PSecurityDescriptor; psidEveryone: PSID; sidAuth: TSidIdentifierAuthority; lSDSize, lACLSize: Cardinal; lpACL: PACL; begin Result := False; pSD := nil; psidEveryone := nil; try SA.nLength := SizeOf(TSecurityAttributes); SA.lpSecurityDescriptor := nil; SA.bInheritHandle := False;
sidAuth := SECURITY_WORLD_SID_AUTHORITY; if not AllocateAndInitializeSid(sidAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, psidEveryone) then begin Exit; end; lSDSize := SizeOf(TSecurityDescriptor); lACLSize := GetLengthSID(psidEveryone) + SizeOf(TAccessAllowedACE) + SizeOf(TACL); pSD := HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, lSDSize + lACLSize); if pSD = nil then begin Exit; end; if not InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION) then begin Exit; end; lpACL := PACL(PChar(pSD) + lSDSize); if not InitializeAcl(lpACL^, lACLSize, ACL_REVISION) then begin Exit; end; if not AddAccessAllowedAce(lpACL^, ACL_REVISION, FILE_ALL_ACCESS {FILE_GENERIC_READ or FILE_GENERIC_WRITE}, psidEveryone) then begin Exit; end; if not SetSecurityDescriptorDacl(pSD, True, lpACL, False) then begin Exit; end; SA.lpSecurityDescriptor := pSD; Result := True;
finally if psidEveryone <> nil then FreeSID(psidEveryone); if (Result = False) and (pSD <> nil) then HeapFree(GetProcessHeap, 0, pSD); end; end;
-
> 1. Как задать первый параметр в CreateMutex таким образом, > чтобы любой эккаунт мог выполнить CreateMutex без ошибки > недостаточности прав?
var
SD: TSecurityDescriptor;
SA: TSecurityAttributes;
Win32Check(InitializeSecurityDescriptor(@SD, SECURITY_DESCRIPTOR_REVISION);
Win32Check(SetSecurityDescriptorDacl(@SD, true, nil, false));
SA.nLength:= SizeOf(SA);
SA.lpSecurityDescriptor := @SD;
SA.bInheritHandle := False;
Mutex:= CreateMutex(@SA, false, 'Mymutex');
> 2. Как поведет себя Win98, если в нем выполнить CreateMutex > с заданием прав?
Ей по барабану.
-
Эта ежель доступ ваще всем и кажнему. Ежель группе "Все", то чуток сложнее. А ежель нать, шоб меж терминальными сессиями видать было, то имя "Global\MyMutex"
-
> где-то так...
Не проще ли nil в качестве DACL задать? ;)
> 2. Как поведет себя Win98, если в нем выполнить CreateMutex > с заданием прав?
Вылетит при старте приложения, наверное, так как DLL вы видимо подключаете статически, а на Win9x функций для управления безопасности нет.
-
> [4] Ins © (16.04.08 13:26)
там они есть, но в виде заглушек.
-
> там они есть, но в виде заглушек.
Возможно, я этот вопрос не исследовал, поверю на слово ;)
-
А вот посмотрите, правильно перевел код Игорь Шевченко на C#
BOOL
CreateAccessSA(
SECURITY_ATTRIBUTES * SA
)
lSDSize = sizeof(SECURITY_DESCRIPTOR);
lACLSize = GetLengthSid(psidEveryone) + sizeof(ACCESS_ALLOWED_ACE) + sizeof(ACL);
if ((pSD = HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, lSDSize + lACLSize)) == NULL)
if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
lpACL = (PACL)pSD + lSDSize;
if (!InitializeAcl(lpACL, lACLSize, ACL_REVISION))
if (!AddAccessAllowedAce(lpACL, ACL_REVISION, FILE_ALL_ACCESS, psidEveryone))
if (!SetSecurityDescriptorDacl(pSD, true, lpACL, false))
SA->lpSecurityDescriptor = pSD;
cleanup:
if (psidEveryone != NULL)
FreeSid(psidEveryone);
if (pSD != NULL)
HeapFree(GetProcessHeap, 0, pSD);
return Result;
}
-
Ссори, код конечно не Игорь Шевченко, а Игоря Шевченко :)
-
Блин и код перевел не Игорь Шеченко, а я :) Чорт возьми, плохо без редактирования ;) Кстати, не так много качественной инфы по этой теме, респект за код ИШ.
-
> [8] bycka (04.06.08 17:57) > Ссори, код конечно не Игорь Шевченко, а Игоря Шевченко
и не на C#, а на C++ )
|