Jenifer 0 Posted December 6, 2020 Hello, I am trying to find size of built-in classes for an example TControl,TWinControl etc.Tried with InstanceSize() which in turn might not add size of few types considering them as references. Found an interesting stack-overflow thread talking about TMemoryStream to find out class size:https://stackoverflow.com/questions/8782518/getting-the-size-of-a-class-or-object-in-the-same-format-as-a-file-size.I couldn't get much info on how to use TMemoryStream to figure out class size,can i get assistance regarding this? Thanks, Jenifer Share this post Link to post
David Heffernan 2345 Posted December 6, 2020 This is very complex. The answer you link to is the size when serialized. But that bears no real relation to the memory used by the class at runtime. Also there are the system resources that are used. The real question though is what you are planning to use this value for. Knowing that would allow us to understand better how you might solve this. Share this post Link to post
Jenifer 0 Posted December 6, 2020 Thanks @David Heffernan Yeah better let me put my use case first: I want to capture properties of delphi UI controls starting with base controls TControl,TWinControl. Have my own rough structures for TControl/TWinControl(in C programming), but those sizes aren't matching with controls of Delphi 10.4(3) versions. So wanted to check sizes of those in-built control classes, tried with InstanceSize() which doesn't seem to be returning actual size I got to know about TMemoryStream while searching for a solution Any efficient/working solution would be great!!!:-) Share this post Link to post
David Heffernan 2345 Posted December 6, 2020 (edited) You don't need to know the size of anything to persist properties. The way to do that is to use the streaming framework. There are many example codes on the web. You are probably making a mistake in believing that you need to copy a block of memory. That's not how to do persistence of complex structures. Edited December 6, 2020 by David Heffernan Share this post Link to post
Arnaud Bouchez 407 Posted December 6, 2020 Asking the very same question here and in SO is not very fair. Share this post Link to post
Remy Lebeau 1397 Posted December 6, 2020 4 hours ago, Jenifer said: I want to capture properties of delphi UI controls starting with base controls TControl,TWinControl. You do know that the RTL has its own native streaming framework for that exact purpose, don't you? It is called a DFM. It is not just for designing Forms at design-time. It can be used by anyone to stream any TPersistent-derived class, which includes UI controls. Look at the TStream.WriteComponent() and TStream.ReadComponent() methods. 4 hours ago, Jenifer said: Have my own rough structures for TControl/TWinControl(in C programming), but those sizes aren't matching with controls of Delphi 10.4(3) versions. This implies to me that you are probably using overlay classes in C++ (C doesn't have classes) to access private members of those UI classes, by aligning members of the overlay class to coincide with the members of the UI classes. You should not be doing that. But even if you were, there are better ways to access private members, such as this template trick (and this follow-up). 4 hours ago, Jenifer said: So wanted to check sizes of those in-built control classes, tried with InstanceSize() which doesn't seem to be returning actual size Yes, it does. It just doesn't report the size you are thinking of. It only reports the size of the class itself (same as sizeof() does in C/C++), but it does not account for any additional memory that members of that class allocate dynamically for themselves internally (strings, lists, buffers, etc). 4 hours ago, Jenifer said: I got to know about TMemoryStream while searching for a solution That only works if you are serializing a class into a stream. You are getting the total flat size of the data the class wrote to the stream, not the size of the class itself. 1 Share this post Link to post
Jenifer 0 Posted December 7, 2020 8 hours ago, Arnaud Bouchez said: Asking the very same question here and in SO is not very fair. ,due to urgency I had posted there as well, based on responses will stick to one going further. 1 Share this post Link to post
Jenifer 0 Posted December 9, 2020 On 12/7/2020 at 4:56 AM, Remy Lebeau said: You do know that the RTL has its own native streaming framework for that exact purpose, don't you? It is called a DFM. It is not just for designing Forms at design-time. It can be used by anyone to stream any TPersistent-derived class, which includes UI controls. Look at the TStream.WriteComponent() and TStream.ReadComponent() methods. This implies to me that you are probably using overlay classes in C++ (C doesn't have classes) to access private members of those UI classes, by aligning members of the overlay class to coincide with the members of the UI classes. You should not be doing that. But even if you were, there are better ways to access private members, such as this template trick (and this follow-up). Yes, it does. It just doesn't report the size you are thinking of. It only reports the size of the class itself (same as sizeof() does in C/C++), but it does not account for any additional memory that members of that class allocate dynamically for themselves internally (strings, lists, buffers, etc). That only works if you are serializing a class into a stream. You are getting the total flat size of the data the class wrote to the stream, not the size of the class itself. Thanks a lot for your detailed answer. The way we capture UI control properties is bit different via C programming, hence I doubt if I could go with DFM approach. My premier requirement here is finding basic control's memory offsets of various members, so that capture can go smooth. Share this post Link to post
David Heffernan 2345 Posted December 9, 2020 33 minutes ago, Jenifer said: Thanks a lot for your detailed answer. The way we capture UI control properties is bit different via C programming, hence I doubt if I could go with DFM approach. My premier requirement here is finding basic control's memory offsets of various members, so that capture can go smooth. It seems like you might have asked the wrong question. It doesn't sound as though the size is that important. What you seem to be after is to capture the control's properties. Is that correct? Share this post Link to post
Jenifer 0 Posted December 9, 2020 2 minutes ago, David Heffernan said: It seems like you might have asked the wrong question. It doesn't sound as though the size is that important. What you seem to be after is to capture the control's properties. Is that correct? We have framework to capture Delphi application control properties, it is that there are some issues related to 10.4 version. More related to memory offset, there came the question about size of basic Control classes like TControl/TWinControl. Share this post Link to post
David Heffernan 2345 Posted December 9, 2020 If what you are really asking about is the size of the instance, then use InstanceSize to find that out. Share this post Link to post
Remy Lebeau 1397 Posted December 9, 2020 4 hours ago, Jenifer said: The way we capture UI control properties is bit different via C programming, hence I doubt if I could go with DFM approach. My premier requirement here is finding basic control's memory offsets of various members, so that capture can go smooth. The offsets of members should not matter, unless you are doing something low-level to access the underlying raw memory data directly. You are going to have to provide more detailed information about what you are really trying to accomplish. Right now, it is very confusing to understand without seeing exactly what you are working with. 3 hours ago, Jenifer said: We have framework to capture Delphi application control properties, it is that there are some issues related to 10.4 version. More related to memory offset, there came the question about size of basic Control classes like TControl/TWinControl. Is it a 3rd party framework that we can see online, or is it something custom you developed for yourself? What issues is it having in 10.4 that it doesn't have in previous versions? Share this post Link to post
Jenifer 0 Posted December 9, 2020 @Remy Lebeau,Thanks for your reply. Yes, it is our own custom library that we had developed. From the window of Delphi application, I am trying to read Delphi object & its properties. We do maintain our own structures for TControl & TWinControl etc. Facing access violation issue on trying to read text from the UI control like panel via sending message. Just wondering it might be due to structural change in Delphi UI control classes after 2006(That was the last developed/modified one) Thanks, Jenifer Share this post Link to post
Remy Lebeau 1397 Posted December 9, 2020 19 minutes ago, Jenifer said: From the window of Delphi application, I am trying to read Delphi object & its properties. You don't need direct access to an object's raw memory in order to do that. Use RTTI instead, that is what it is meant for. 19 minutes ago, Jenifer said: We do maintain our own structures for TControl & TWinControl etc. Why? 19 minutes ago, Jenifer said: Facing access violation issue on trying to read text from the UI control like panel via sending message. That is certainly a risk when you assume a certain memory layout, and then that layout changes between compiler/RTL versions. 19 minutes ago, Jenifer said: Just wondering it might be due to structural change in Delphi UI control classes after 2006(That was the last developed/modified one) That is quite likely. As new features get added over time, new members are added, existing members get moved around, etc. Share this post Link to post
David Heffernan 2345 Posted December 9, 2020 Does your code run in the same process as the Delphi program whose properties you are trying to inspect? Share this post Link to post
Jenifer 0 Posted December 9, 2020 (edited) 2 minutes ago, David Heffernan said: Does your code run in the same process as the Delphi program whose properties you are trying to inspect? Nope,those are of separate process Edited December 9, 2020 by Jenifer Share this post Link to post
David Heffernan 2345 Posted December 9, 2020 Just now, Jenifer said: Nopethose are of separate process Kind of an important detail that you slipped in there. I'm going to be blunt here. The process of trying to offer help whereby you provide minimal details and then we try to piece together your environment with a game of 20 questions. Well, it's not productive. You haven't had a whole lot of success in this thread because you have been so economical with these details. Until you address this lack of detail, I predict nothing will change. Share this post Link to post
Jenifer 0 Posted December 9, 2020 21 minutes ago, Remy Lebeau said: You don't need direct access to an object's raw memory in order to do that. Use RTTI instead, that is what it is meant for. Why? That is certainly a risk when you assume a certain memory layout, and then that layout changes between compiler/RTL versions. That is quite likely. As new features get added over time, new members are added, existing members get moved around, etc. Pseudo might be like this: It is something like we would get Window(HWnd), object from an application. Cast that object to TControl*(which is own own structure in C),so that we can retrieve properties No issues till now but when i try to retrieve a text from control via WM_GETTEXT is what i am facing issue with. Thanks for your time, appreciate it!! Share this post Link to post
Jenifer 0 Posted December 9, 2020 Hopefully I had cleared the air with recent reply!!Let me rephrase my question probably. Assuming TControl,TWinControl have class members starting as below: {$IF DEFINED(CLR)} TControl = class(TComponent, IControl) {$ELSE} TControl = class(TComponent) {$ENDIF} public FParent: TWinControl; FWindowProc: TWndMethod; FLeft: Integer; FTop: Integer; FWidth: Integer; FHeight: Integer; FControlStyle: TControlStyle; FControlState: TControlState; FDesktopFont: Boolean; FVisible: Boolean; FEnabled: Boolean; {$IF DEFINED(CLR)} TWinControl = class(TControl, IWinControl) strict private class var FPendingParentWindow: HWND; {$ELSE} TWinControl = class(TControl) {$ENDIF} private class var RM_AsyncMessage: Cardinal; private FAlignControlList: TList; FAlignLevel: Word; FBevelEdges: TBevelEdges; FBevelInner: TBevelCut; FBevelOuter: TBevelCut; FBevelKind: TBevelKind; FBevelWidth: TBevelWidth; FBorderWidth: TBorderWidth; FPadding: TPadding; FBrush: TBrush; FDockClients: TList; How do we know the offset of each member in TControl/TWinControl class? For an example offset of FParent,FWidth like that. I had to dive into disassembly to figure out the offset values ,but i could find offsets of few members only not for all. Any suggestions? Thanks, Jenifer Share this post Link to post
David Heffernan 2345 Posted December 9, 2020 For methods that are readily accessible you can use the idea given here (Delphi: Offset of record field - Stack Overflow), although in that Q it's in the context of records. Your TControl in the previous message has public methods, so that's easy. Your TWinControl has private methods so you'd need some form of cracker to gain access to the private methods. If it were me I'd copy the VCL unit, add it to my project, and add some code in the implementation section to dump out the info you require. Of course, the TControl that you quote here isn't the real TControl since the fields in the real one are private not public. So who knows what is really going on. Perhaps you are posting code from some experiment you are working on. Also, casting an HWND to a TControl* doesn't get you anywhere. They are not the same thing. 1 Share this post Link to post
Jenifer 0 Posted December 9, 2020 7 minutes ago, David Heffernan said: For methods that are readily accessible you can use the idea given here (Delphi: Offset of record field - Stack Overflow), although in that Q it's in the context of records. Your TControl in the previous message has public methods, so that's easy. Your TWinControl has private methods so you'd need some form of cracker to gain access to the private methods. If it were me I'd copy the VCL unit, add it to my project, and add some code in the implementation section to dump out the info you require. Of course, the TControl that you quote here isn't the real TControl since the fields in the real one are private not public. So who knows what is really going on. Perhaps you are posting code from some experiment you are working on. Also, casting an HWND to a TControl* doesn't get you anywhere. They are not the same thing. No,I didn't mean casting HWND to TControl*.It is the Delphi object we will retrieve from the application Window. Yes, of course am playing around the VCL unit code, had pasted those ones for reference.(So no public fields even from TControl :-)) Thanks Share this post Link to post
Remy Lebeau 1397 Posted December 9, 2020 2 hours ago, Jenifer said: How do we know the offset of each member in TControl/TWinControl class? Enhanced RTTI provides that information. See Working with RTTI, TRttiType.GetFields(), and TRttiField.Offset. 2 hours ago, Jenifer said: For an example offset of FParent,FWidth like that. For example: var Ctx: TRttiContext; Offset: Integer; Offset := Ctx.GetType(TControl).GetField('FParent').Offset; But why do you need to access the FParent and FWidth member directly? Why can't you use the TControl's public Parent and Width properties instead? 1 Share this post Link to post
David Heffernan 2345 Posted December 9, 2020 1 hour ago, Remy Lebeau said: Enhanced RTTI provides that information. See Working with RTTI, TRttiType.GetFields(), and TRttiField.Offset. For example: var Ctx: TRttiContext; Offset: Integer; Offset := Ctx.GetType(TControl).GetField('FParent').Offset; But why do you need to access the FParent and FWidth member directly? Why can't you use the TControl's public Parent and Width properties instead? @Remy read up to the part where all this happens in another process with, presumably, ReadProcessMemory. Share this post Link to post
Remy Lebeau 1397 Posted December 9, 2020 2 hours ago, David Heffernan said: @Remy read up to the part where all this happens in another process with, presumably, ReadProcessMemory. Thanks, I missed that part. In which case, this issue just got a whole lot more dangerous. Manipulating the RTL/VCL's data members directly, behind the RTL/VCL's back, is a HUGE risk. Without intimate and explicit knowledge of the exact version of Delphi the other process is using, you can't hope to access its private data SAFELY, for the very reason I stated earlier - data members can and do change between versions. Share this post Link to post