// 과니입니다
// 2008.04.23 오늘의 팁은 레지스트리 키의 권한 설정입니다.
// 요즘들어 델마당의 팁이나 강좌를 올리는 분들이 없는 것 같아 보여서
// 실력없는 과니가 자꾸만 올리게됩니다.
//
// SAMPLE_REG_KEY는 전체 상수로 테스트를 시행할 레지스트리 키입니다.
// 버튼은 총 4개로 '키생성', '키삭제', '권한설정', 권한해제' 입니다.
// 키 생성을 하신 후에 권한 설정하시고 키삭제를 하려고하면 삭제가 실패될것입니다.
// 레지스트리키에 권한이 설정되어 삭제되지 않는 것이며 이것은 Regedit.exe로 실행하셔도 마찬가지 입니다.
// 하지만 키가 아닌 내용은 삭제 되더군요...ㅋㅋㅋ
//
// 다음 강좌는 뭘로 정할지 찾아보러 ㅎㄷㄷ

const

// 테스트를 시행할 레지스트리 키 상수
    SAMPLE_REG_KEY = 'Software\REGSAMPLE';


procedure TForm2.btnProtectKeyClick(Sender: TObject);
begin
    // 해당 키 권한 설정
    if ProtectKey(HKEY_LOCAL_MACHINE, SAMPLE_REG_KEY) = ERROR_SUCCESS then
       
ShowMessage('권한 설정 완료')
    else
       
ShowMessage(
'권한 설정 실패');
end;

procedure TForm2.btnUnProtectKeyClick(Sender: TObject);
begin
    // 해당 키 권한 해제
    if UnProtectKey(HKEY_LOCAL_MACHINE, SAMPLE_REG_KEY) = ERROR_SUCCESS then
        ShowMessage('권한 해제 완료')
    else
        ShowMessage('권한 해제 실패');
end;

procedure TForm2.btnCreateRegKeyClick(Sender: TObject);
var
    phkResult : hKey;
begin
    // 레지스트리 키 생성
    if RegCreateKey(HKEY_LOCAL_MACHINE, SAMPLE_REG_KEY, phkResult) = ERROR_SUCCESS then begin
        ShowMessage('생성 완료');
    end else begin
        ShowMessage('생성 오류');
    end;
end;

procedure TForm2.btnDeleteRegKeyClick(Sender: TObject);
begin
    // 레지스트리 키 삭제
    if RegDeleteKey(HKEY_LOCAL_MACHINE, SAMPLE_REG_KEY) = ERROR_SUCCESS then begin
        ShowMessage('삭제 완료');
    end else begin
        ShowMessage('삭제 오류');
    end;
end;

function OpenOrCreateKey(hKey : Cardinal; lpSubKey : String; var phkResult : hKey; fCreate : Boolean = True) : Integer;
begin
    // 레지스트리 키 검색
    if RegOpenKeyEx(hKey, PChar(lpSubKey), 0, KEY_ALL_ACCESS, phkResult) = ERROR_SUCCESS then begin
        Result := RegOpenKey(hKey, PChar(lpSubKey), phkResult);
        if Result = ERROR_SUCCESS then begin
            if fCreate then Result := RegCreateKey(hKey, PChar(lpSubKey), phkResult);
        end;
    end else begin
        Result := RegOpenKey(hKey, PChar(lpSubKey), phkResult);
        if Result = ERROR_SUCCESS then begin
            if fCreate then Result := RegCreateKey(hKey, PChar(lpSubKey), phkResult);
        end;
    end;
end;

// 해당 레지스트리 키의 권한을 해제하는 함수
function
UnProtectKey(hRKey : Cardinal; lpSubKey : String) : Integer;
var
    SecDes : TSECURITYDESCRIPTOR;
    hRegKey : hKey;
begin
    InitializeSecurityDescriptor(@SecDes, SECURITY_DESCRIPTOR_REVISION);

    Result := OpenOrCreateKey(hRKey, lpSubKey, hRegKey);

    if Result = ERROR_SUCCESS then begin
        SetSecurityDescriptorDacl(@SecDes, True, nil, False);
        Result := RegSetKeySecurity(hRegKey, DACL_SECURITY_INFORMATION, @SecDes);
    end;
end;

// 해당 레지스트리 키의 권한을 설정하는 함수
function
ProtectKey(hRKey : Cardinal; lpSubKey : String) : Integer;
const
    ACL_REVISION = 2;
var
    SecDes : TSECURITYDESCRIPTOR;

    ACLBuffer: array[1..1024] of Byte;

    ptACL : PACL;
    hRegKey : hKey;
begin
    InitializeSecurityDescriptor(@SecDes, SECURITY_DESCRIPTOR_REVISION);
    ptACL:= @ACLBuffer;
    InitializeAcl(ptACL^, SizeOf(ACLBuffer), ACL_REVISION);

    Result := OpenOrCreateKey(hRKey, lpSubKey, hRegKey);

    if Result = ERROR_SUCCESS then begin
        SetSecurityDescriptorDacl(@SecDes, True, ptACL, False);
        Result := RegSetKeySecurity(hRegKey, DACL_SECURITY_INFORMATION, @SecDes);
    end;
end;