Jump to content

DelphiUdIT

Members
  • Content Count

    612
  • Joined

  • Last visited

  • Days Won

    11

Everything posted by DelphiUdIT

  1. DelphiUdIT

    Library for modifying windows PE files?

    This is part of project "Cmulator" made in Pascal. This is the license: https://github.com/Coldzer0/Cmulator/blob/master/LICENSE
  2. DelphiUdIT

    Breakpoints do not work.

    First of all, look if you are in debug profile, like @Remy Lebau wrote: look at the Project explorer after look at "Project/Options" menu: You must look if there are some advise of line end char of your source file : end of line char should be CR+LF, if not debugger (as IDE) may not work as expected. Bye
  3. DelphiUdIT

    Thread and free

    In the Queue procedure you are using resources allocated in the Anonymous TASK, I don't think it is correct to "free" them that way: when references to lTstrings in the Main Thread are used (asynchronously from your try / finally) these will have to exist... and you however, you "free" them sequentially to your program flow. I honestly don't know how to resolve the situation with the example you gave. However, I could have made a mistake in the analysis, but I am still curious about the comment of someone who is certainly more expert than me. Bye @Cristian Peța sorry for duplicate, we have write at the same time.
  4. DelphiUdIT

    form principale parte dopo un altra form

    Ciao, siamo in un forum internazionale. Dovresti esprimerti in inglese. Hi, we are in an international forum. You should express yourself in English. The list of forms in use in the program is displayed in the "Project/Options" menu Forms that should not be displayed during creation must have the VISIBLE property set to false, view and change the property from the Object Inspector. You must set the property in each individual Form. At runtime if you need to display a Form you must call the SHOW method of the Form itself, example: Form2.Show Obviously it must have already been created either because it is in the "Auto Create Form" list above or because it was created at runtime.
  5. Try this: go to the "mehtcommserverLib_tlb.pas" file (which is already open in the IDE), go to the beginning of the file and in one of the lines you will see where it was derived from, i.e. the DLL to register. Example: You must find a DLL with the name very similar to that (your name of course) After found the DLL, run from command prompt (AS ADMIN): regsvr32 nameofdll.dll where nameofdll.dll is the dll that is named in the file. I hope it is useful to you. EDIT: the extension may be also OCX, EXE, ...
  6. Take care that on 64 bit you cannot mix pascal code and asm code and that the parameters of a method will be passed differently with respect to 32 bits (the conventions for passing through registers change): for example a 64-bit integer as a function result in a 32-bit app will be passed as EDX:EAX while in a 64-bit app it will be passed as RAX. Also, the asm code should be rewrite. No mix between 32 bit asm and 64 bit asm should be done. Of course 32 bit registers may be accessed, but not all 64 bit instructions are available to do the same as 32 bit with 32 bit register.
  7. DelphiUdIT

    C++ / windows.h and data alignment

    @alank2 said that, he compiles the windows sdk headers (if that is what he means) with BCC32 !!! and I asked why ... but never mind may be I understood wrong.
  8. He's talking about DELPHI 7 !!! and my explanation is about DELPHI 7 to Delphi 10.3 differences (surely only some of them)...
  9. I have no knowledge of any tool for automatic conversion (even partial). There are several contexts you should pay attention to when converting: 1) string: currently the definition is Unicode, in Delphi7 it was synonymous with AnsiString; 2) char: 1 character occupies two bytes. in Delphi7 it occupied 1 byte; 3) several definitions have changed in both core and third-party components; 4) several basic components distributed with Delphi7 are no longer distributed with Delphi 10.3, and obviously there must be third-party 64-bit components if you use them; 5) when converting between 32 and 64 bit you must pay attention to the various types of parameters, especially in third-party DLLs: PChar, PWChar, PAnsiChar.... 6) Integer, cardinal, nativeint, etc.... 7) Floating Extended type is 80 bit long in 32 bit application, but in 64 bit is an alias of double (64 bit long); 8 Pointers in 32 bit platforms are 4 bytes length, in 64 bit platforms they are 8 bytes length. 9) In 64 bit platforms you cannot mix assembler and pascal in the same method. 10) more other stuff Look here for more info: https://docwiki.embarcadero.com/RADStudio/Rio/en/Converting_32-bit_Delphi_Applications_to_64-bit_Windows Good luck and good work
  10. DelphiUdIT

    C++ / windows.h and data alignment

    My fault, sorry ... since the first post talked about "vcl.h" and in others the references to the compilation of "bcc32" were reported, I considered the discussion linked to the Embarcadero C++ environment. What is the reason for using Microsoft SDK headers instead of Embarcadero ones? I don't use C++ very often and when I need to I use Rad Studio on Windows or gcc on Linux. And I have never had any problems using the APIs (with the original headers of the respective environments). If I have to use "packed" structures, I septate and restore alignment. In Delphi, where there is no possibility to "push/pop" the settings, I have a small structure that I test to find out the original alignment and then restore it at the end of my needs. The example I gave in the previous post on the "imagedosheader" was the first alignment mistake (happened many decades ago) and at the time it drove me crazy...
  11. DelphiUdIT

    C++ / windows.h and data alignment

    This is "mine" windows.h first lines ... and there is an alignment forced at 8 bytes.
  12. DelphiUdIT

    Use of dynamic control names

    You are right. But I normally use it with Panels, GroupBoxs, or such containers and inside them I put only few controls. I use it for example to enable controls with various login and disable them after logout, I found it very simple, and manipulating the tag value only (1K = Login Level 1, 2K = Login Level 2, etc ...). If I need to modify only some properties, I don't need to know the class of the controls ... eg. Enabled, Visible are common to all TControls so not needs explicit use of "(CB as TButton)" ... or "IF (CB is TButton)" But like some others wrote there are more methods, surely better than this. N.B.: very often I create a lot of controls at runtime, and in that way assigning a tag value is enough. I don't need list or static enumeration.
  13. DelphiUdIT

    C++ / windows.h and data alignment

    I commented "vcl.h" (i don't use it) and put "windows.h" at the top. Same result, no warnings (Rad Studio 11.3).
  14. DelphiUdIT

    Use of dynamic control names

    One of the various ways is to "cycle" within the controls of the parent component: to identify the affected control you could give a value to the tag property during the design phase (for example from 1000 to the first Button, 1001 to the second, etc. ..), then this will be the code assuming you are looping through the controls of a Form (Form1): var CB: TControl; for var i := 0 to Form1.ControlCount-1 do begin CB := Form1.Controls[i]; if (CB is TButton) and ((CB as TButton).Tag > 1000) then begin (CB as TButton).Enabled := True; end; end;
  15. DelphiUdIT

    C++ / windows.h and data alignment

    I added the "#pragma pack" in one of my projects, but don't have this kind of Warning:
  16. DelphiUdIT

    C++ / windows.h and data alignment

    Windows API calls are generally 8-byte aligned on a 64-bit system. Compared to APIs, VCLs are simply wrappers and do not modify the structures. The result (outgoing) and the data (incoming) are and must conform to what is documented by Microsoft, the VCLs do not test, change or modify anything with respect to this, much less the required alignment. Where necessary, the includes files define the correct alignments if a different alignment is necessary (this in both C++ and Delphi) as required by the API. An example for everyone is the very old (almost archaic) definition of the _ImageDosHeader which is aligned to 2 bytes. Bye
  17. DelphiUdIT

    How do I execute code after FormShow ?

    You can find the WM_USER+xxxx used by Embarcadero components by running a grep -i -d WM_USER *.pas from the "source" directory in your Delphi installation (at least for versions that also have the source distribution). However, what should be clear is that Windows messages must be directed directly to a handle (therefore specific control). It is therefore absolutely not a given that a WM_USER+100 used for example in Vcl.DBGrids cannot be used within the application. And I would say that it would be somewhat "questionable" that WM messages are used internally by Embarcadero components in a generic manner and not "privately" solely and exclusively for that component.
  18. DelphiUdIT

    How can I get this code formatting ?

    It was is Rio too, but i remember that were some issuse about that. First the errorinsight was not working, but the compilation were OK. Other issues ,,, may be I think that no one used in that version the inline variables. Bye
  19. @Tommi Prami If you want commit the code in your repository and insert the test for the available of RDRAND and RDSEED, this is the code. Project Jedi has more info about that and of course the Intel documentation has all the documentation. I don't know about AMD, so i presume that AMD has the same two bits in use (hope). Tested in Win32 and Win64 Protected Mode, tested in virtual mode (WINXP - WIN11 32 bit and 64 bit), not tested in real address mode. interface //Explicity check if RDRAND and RDSEEK ara avilable //Global use TCheck_RDRAND_RDSEED = record tc_RDRAND: boolean; //true if RDRAND is available tc_RDSEED: boolean; //true if RDSEED is available end; var RDRAND_RDSEED_Available: TCheck_RDRAND_RDSEED; implementation const //ID string to identify CPU Vendor, the are a multitude .. but we focalize on this VendorIDxIntel: array [0..11] of AnsiChar = 'GenuineIntel'; VendorIDxAMD: array [0..11] of AnsiChar = 'AuthenticAMD'; //Internal functions, may be usefull to implement other check //Tested in Win32 and Win64 Protected Mode, tested in virtual mode (WINXP - WIN11 32 bit and 64 bit), not tested in real address mode //The Intel Documentation has more detail about CPUID //Jedi project has implemented TCPUInfo with more details. //First check that the CPU supports CPUID instructions. There are some exceptions with this rule, //but with very very old processors function Is_CPUID_Valid: boolean; register; asm {$IFDEF WIN64} pushfq //Save EFLAGS pushfq //Store EFLAGS xor qword [esp], $00200000 //Invert the ID bit in stored EFLAGS popfq //Load stored EFLAGS (with ID bit inverted) pushfq //Store EFLAGS again (ID bit may or may not be inverted) pop rax //eax = modified EFLAGS (ID bit may or may not be inverted) xor rax, qword [esp] //eax = whichever bits were changed popfq //Restore original EFLAGS and RAX, $00200000 //eax = zero if ID bit can't be changed, else non-zero jz @quit mov RAX, $01 //If the Result is boolean, the return parameter should be in A??? (true if A??? <> 0) @quit: {$ELSE} pushfd //Save EFLAGS pushfd //Store EFLAGS xor dword [esp], $00200000 //Invert the ID bit in stored EFLAGS popfd //Load stored EFLAGS (with ID bit inverted) pushfd //Store EFLAGS again (ID bit may or may not be inverted) pop eax //eax = modified EFLAGS (ID bit may or may not be inverted) xor eax,[esp] //eax = whichever bits were changed popfd //Restore original EFLAGS and eax, $00200000 //eax = zero if ID bit can't be changed, else non-zero jz @quit mov EAX, $01 //If the Result is boolean, the return parameter should be in AL (true if AL <> 0) @quit: {$ENDIF} end; //1) Check that the CPU is an INTEL CPU, we don't know nothing about other's // We can presume the AMD modern processors have the same check of INTEL, but only for some instructions. // No test were made to verify this (no AMD processor available) // //2) Catch the features of the CPU in use // //3) Catch the new features of the CPU in use // procedure CPUID_GeneralCall(InEAX: cardinal; InECX: cardinal; out Reg_EAX, Reg_EBX, Reg_ECX, Reg_EDX); stdcall; asm {$IFDEF WIN64} // save context PUSH RBX // CPUID MOV EAX, InEAX //Generic function MOV ECX, InECX //Generic sub function // //For CPU VENDOR STRING EAX := $0 //ECX is not used when EAX = $0 // //For CPU Extension EAX := $01 //ECX is not used when EAX = $01 // //For CPU New Extension EAX := $07 //ECX should be $00 to read if RDSEED is available // CPUID // store results MOV R8, Reg_EAX MOV R9, Reg_EBX MOV R10, Reg_ECX MOV R11, Reg_EDX MOV Cardinal PTR [R8], EAX MOV Cardinal PTR [R9], EBX MOV Cardinal PTR [R10], ECX MOV Cardinal PTR [R11], EDX // restore context POP RBX {$ELSE} // save context PUSH EDI PUSH EBX // CPUID MOV EAX, InEAX //Generic function MOV ECX, InECX //Generic sub function // //For CPU VENDOR STRING EAX := $0 //ECX is not used when EAX = $0 // //For CPU Extension EAX := $01 //ECX is not used when EAX = $01 // //For CPU New Extension EAX := $07 //ECX should be $00 to read if RDSEED is available // CPUID // store results MOV EDI, Reg_EAX MOV Cardinal PTR [EDI], EAX MOV EAX, Reg_EBX MOV EDI, Reg_ECX MOV Cardinal PTR [EAX], EBX MOV Cardinal PTR [EDI], ECX MOV EAX, Reg_EDX MOV Cardinal PTR [EAX], EDX // restore context POP EBX POP EDI {$ENDIF} end; //Function called from Initialization function CPUID_RDRAND_RDSEEK_Check: TCheck_RDRAND_RDSEED; var tempVendorId: array [0..11] of AnsiChar; HighValBase: Cardinal; HighValExt1: Cardinal; VersionInfo: Cardinal; AdditionalInfo: Cardinal; ExFeatures: Cardinal; StdFeatures: Cardinal; UnUsed1, UnUsed2: Cardinal; NewFeatures: Cardinal; begin Result.tc_RDRAND := false; Result.tc_RDSEED := false; //Check if CPUID istruction is valid testing the bit 21 of EFLAGS if Is_CPUID_Valid then begin //Get the Vendor string with EAX = 0 and ECX = 0 CPUID_GeneralCall(0, 0, HighValBase, tempVendorID[0], tempVendorID[8], tempVendorID[4]); //Verifiy that we are on CPU that we support if (tempVendorId = VendorIDxIntel) OR (tempVendorId = VendorIDxAMD) then begin //Now check if RDRAND and RDSEED is supported inside the extended CPUID flags if HighValbase >=1 then //Supports extensions begin //With EAX = 1 AND ECX = 0 the Extension and the available of RDRAND can be read CPUID_GeneralCall(1, 0, VersionInfo, AdditionalInfo, ExFeatures, StdFeatures); //ExFeatures (ECX register) bit 30 is 1 if RDRAND is available if (ExFeatures and ($1 shl 30)) <> 0 then Result.tc_RDRAND := true; if HighValBase >= 7 then begin //With EAX = 7 AND ECX = 0 the NEW Extension and the available of RDSEED can be read CPUID_GeneralCall(7, 0, HighValExt1, NewFeatures, UnUsed1, UnUsed2); //New Features (EBX register) bit 18 is 1 if RDSEED is available if (NewFeatures and ($1 shl 18)) <> 0 then Result.tc_RDSEED := true; end; end; end; end; end; Initialization begin RDRAND_RDSEED_Available := CPUID_RDRAND_RDSEEK_Check; end; end. Bye
  20. I also think we are misunderstanding each other. To close, without going too OT, what you said is clear but we are confusing the issues. The virtualized environment is one thing and is defined through VMX virtualization and other things are the various modes in which the various processes can run (Protect, Real, etc ...). NORMAL PROCESS (NOT VIRTUALIZED) In Intel hardware, the RING0 level is the level that has the highest priority and privilege for instructions in all modes. Very similar to RING1 and RING2, but which have major limitations on the use of privileged instructions. In fact, to the best of my knowledge, RING1 and RING2 are never used (with the exception of RING1 in VMX, or better in the real world implementation like in VirtualBox). RING3 is used for user processes, because it has the lowest privilege level and therefore everything that happens can be monitored by RING0. For example, a fault in the instructions at the RING3 level is managed by the RING0 (normally Kernel) to implement the appropriate countermeasures (which can be either effective repair of the operation such as its emulation, or the management of a "page fault" or its actual rejection with generation of an error (and if this does not come from a user program but from a driver or the kernel then the infamous BSOD will most likely appear). These functions have existed more or less since the first I386 was marketed. Then gradually perfected until we reach our times. All exception management at the instruction level (which obviously also concerns the hardware) is normally managed at the kernel level which can decide to do what it deems most appropriate. VIRTUALIZATION The virtualization process goes beyond this... a new level of control called VMX ROOT is inserted which runs with privileges in a certain sense superior to those of a RING0 and which normally uses the VMX NOT ROOT environment to run another system operating. This is the difference. Then, to make things easier, normally RING1 (ALWAYS IN VMX NOT ROOT) is used to run the guest OS and RING3 (ALWAYS IN VMX NOT ROOT) for user applications. While the VMX ROOT must coordinate with the normal HOST operating system, the VMX NOT ROOT has nothing to do with the host. The CUPID instruction of your GUEST is not managed by the HOST operating system nor from the GUEST KERNEL, but rather by the VMX ROOT which will do what it has to do (it could easily execute it on behalf of the VMX NOT ROOT and report the result perhaps masked). Why don't we see a pronounced slowdown in guest operating systems? Because none of these perform certain operations continuously. Do you really think that a kernel, like a driver or an application, continuously executes a CPUID? Among other things, a very heavy instruction (for dozens of machine cycles if I'm not mistaken). This process is very similar (but being in hardware it is obviously more efficient) to what happened before the use of VMX: VirtualBox works in a similar way even without VMX virtualization, again thanks to RING1 and RING3 but obviously with decidedly lower security compared to a VMX environment. To be clear: VirtualBox hypervisor intercept every single CPUID instruction from VMX NOT ROOT to mask the result (the features that they don't support or they don't want exposed to guest) ... for example in the past they didn't support nexted VT-D virtualization and so the relative CPUID features is set to 0 and the virtual guest (kernel o user) saw THAT ... This is announced support for RDSEED (9 years ago) always from VirtualBox: All as I mentioned if we talk about virtualizing 32-bit environments. In 64-bit environments, additional issues are introduced and the techniques are more complex. It's clear to me, but if there were to be any replies I would say to open another thread.
  21. Intel's documentation specifically talks about that chapter regarding NON-ROOT virtualized code. But this does not mean that the software CRASHES, the virtual machine managers (aka supervisor, aka hypervisor) such as VirtualBox or others implement their own ROOT system alongside that of Intel and which outclasses the functioning and runs its own monitor on the entire virtual environment. From what I know, the VirtualBox hypervisor for example runs as VMX ROOT and the virtual machine runs in ring 1 (OS) and ring 3 (user space). VirtualBox performs all checks and handling of all exceptions of both the guest operating system (OS in ring 1) and USER (in ring 3) ... including CPUIDs and all others if they occur. All this for classic 32-bit VMs, while for 64-bit it's all more complex. I would also like to remind you that for any instruction that can generate an exception there is a specific test that can be used and if the test cannot be performed or the test itself fails then the instruction(s) MUST NOT BE USED... including the CPUID. Example to test if the CPUID is available. So, no software should crash if CPUID is used ONLY when it is available, and this is true also for RDRAND and RDSEED of course: Bye
  22. It is natural that if the instruction is not supported by the processor / virtualization environment something will be generated (crash / AV / fault of code / .... ) but this depends on what the virtualization environment is "able to do ". RDRAND itself is expected to throw an exception in a virtualized environment (and depends by settings) :
  23. I don't understand what you mean. The debugger in the disassembly windows doesn't execute the instruction that you see (wrong or right) but the real instruction. And so the results may be unexpected. But they are the right ones. This is because the mnemonic / symbolic view is only ... a view. Bye
  24. I try to force the fault of the instructions (really simple for one, no fault in the other): the rdseed instruction set the register to zero and the CF to zero, after two (2) consecutive executions ; for the rdrand instruction, I was not able to make it in fault state so, at least for the rdseed instruction the register is set to zero (like you told @Kas Ob.) The rdrand instruction appears to be less sensitive to errors than the rdseed.
  25. Lol, more than Intel ...
×