Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 5947711
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 22, 20262026-05-22T17:00:10+00:00 2026-05-22T17:00:10+00:00

I have tricky question and I hope I can explain it well, I want

  • 0

I have tricky question and I hope I can explain it well,
I want to read value from windows registry which is saved by another program that I don’t have its source, but I already know the type of this value and it’s like this:

  _MyData = record
    byteType: Byte;
    encData: PByte;
  end;

byteType indicates the type of this data as integer (1,2,3…) you can forget about this parameter, while encData is an encrypted data using the windows crypt32.dll function (CryptProtectData)
I use the next code to read the value from registry:

procedure TForm1.Button2Click(Sender: TObject);
var
  myData: _MyData;
  reg: TRegistry;
  valueSize: Integer;
begin
  reg := TRegistry.Create;
  try
    if reg.OpenKey(KEY_PATH,false) then
      Begin
        valueSize := reg.GetDataSize(VALUE_NAME);
        reg.ReadBinaryData(VALUE_NAME, myData, valueSize);
      End;
  finally
    reg.Free;
  end;
end;

// KEY_PATH, VALUE_NAME are string Consts.

So, now I have the encrypted data in myData.encData and now I want decrypt it by passing it the CryptUnprotectData function which has this signature:

function CryptUnprotectData(pDataIn: PDATA_BLOB; ppszDataDescr: PLPWSTR; pOptionalEntropy: PDATA_BLOB; pvReserved: Pointer; pPromptStruct: PCRYPTPROTECT_PROMPTSTRUCT; dwFlags: DWORD; pDataOut: PDATA_BLOB): BOOL; stdcall;

First I need to put the encrypted data in a variable of type DATA_BLOB which has this structure:

  _CRYPTOAPI_BLOB = record
    cbData: DWORD;
    pbData: PBYTE;
  end;
  DATA_BLOB = _CRYPTOAPI_BLOB;
  PDATA_BLOB = ^DATA_BLOB;

pbData is the pointer to the encrypted data (I read it from registry), and cbData is the size of the encrypted data, and here is my problem I have the pointer to encrypted data (I already read it from registry ) in myData.encData which is PByte, but I don’t know how to get the size of this data? and if i don’t give the function CryptUnprotectData the right size it always gives nil in the outpout, Any idea how to do this?

Thanks for your help.

Edit:the solution, thanks to Ken Bourassa

  _MyData = packed record
    byteType: Byte;
    encData: array of byte;
  end;

procedure TForm1.Button2Click(Sender: TObject);
var
  myData: ^_MyData;
  reg: TRegistry;
  valueSize: Integer;
  dataIn, dataOut: DATA_BLOB;
begin
  reg := TRegistry.Create;
  try
    if reg.OpenKey(KEY_PATH,false) then
      Begin
        valueSize := reg.GetDataSize(VALUE_NAME);
        GetMem(myData, ValueSize);
        try
          reg.ReadBinaryData(VALUE_NAME, myData^, valueSize);

          dataOut.cbData := 0;
          dataOut.pbData := nil;
          dataIn.cbData := Valuesize - SizeOf(Byte);
          dataIn.pbData := @myData.encData;
          CryptUnprotectData(@dataIn,nil,nil,nil,nil,CRYPTPROTECT_UI_FORBIDDEN,@dataOut);

          //yes, it works, Thank you very much Ken Bourassa


        finally
          FreeMem(myData);
        End;
      End;
  finally
    reg.Free;
  end;

end;
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-22T17:00:11+00:00Added an answer on May 22, 2026 at 5:00 pm

    The size of the data is reg.GetDataSize – SizeOf(Byte)

    But that is now your only problem,

    Your _MyData structure is 8 bytes long. So when you call

    reg.ReadBinaryData(VALUE_NAME, myData, valueSize); 
    

    for any key value longer than 8 bytes, you have some buffer overflow happening. Even if you read a key shorter than 8 bytes, EncData will contain garbage.

    I’d rather go this way:

    _MyData = packed record              
      byteType: Byte;              
      encData: array[0..MaxInt] of byte;            
    end    
    
    procedure TForm1.Button2Click(Sender: TObject);    
    var      
      myData: ^_MyData;
      reg: TRegistry;      
      valueSize: Integer;    
    begin      
      reg := TRegistry.Create;      
      try        
        if reg.OpenKey(KEY_PATH,false) then          
        Begin            
          valueSize := reg.GetDataSize(VALUE_NAME);            
          GetMem(MyData, ValueSize);
          try
            reg.ReadBinaryData(VALUE_NAME, myData^, valueSize); 
            //Do what is needed with MyData. The size of MyData.EncData = Valuesize - SizeOf(Byte)
          finally
            FreeMem(MyData);
          end;
    
        End;      
      finally        
        reg.Free;      
      end;    
    end;
    

    I added the packed keyword to the record definition as I would believe it’s the most likely way it should be declared… But then, it’s all up to the specifications of the application writting the values. I also declared EncData as Array[0..MaxInt] of byte. That’s makes it a VERY bad idea to declare a variable of type _MyData, but is the only way I know of allowing a variable array in a record without forcing to disable range checking. If always running with Range Checking = False in your project is not a concerned (Or you don’t mind switching it on/off where needed in your code), you could declare it as Array[0..0] of byte. I know it should work, I don’t know the specifics of that method as I never really used it.

    EDIT (After being accepted):

    Actually, declaring EncData as Array of byte is just as bad as declaring it as PByte. Array of byte is a reference type (effectively a 4 bytes pointer). If you try to access EncByte[0] in your code, you’ll most likely get an AV. The only reason it works is that you only use @myData.encData (and the fact the record is allocated using GetMem instead). But used like this, you could declare EncData like this :

    _MyData = packed record              
      byteType: Byte;              
      encData: Record end;            
    end    
    

    and this would still work, as, in your example, you don’t really care about the type EncData is declared, you just care about the memory address where it is.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

So I have a "tricky" question, I want to see people opinions. I'm programming
I have what I think is a tricky question, but hopefully someone on here
here's a tricky question... I have default styled input fields (no css added, just
I have the following tricky problem: I have implemented a (rather complicated) class which
I need to have custom checkboxes which wasn't that tricky. I made checkbox_selector to
I have a little tricky question. I have a Telerik Grid with some ClientSide
A slightly tricky SQL question (we are running SQL server 2000). I have the
I have a similar question to this: PHP session timeout callback? Basically, I want
I have a question similar to the Can you override a parent UIView's alpha
I have a tricky question. lets say if we start naming session as :

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.