The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 2,470 other followers

Archive for March 23rd, 2021

Still unsolved since 2015 NetBeans: Bug 251538 – Your Installer is Creating Invalid Data for the NoModify DWORD Key which crashes enumeration of the Uninstall Key in at least PowerShell

Posted by jpluimers on 2021/03/23

Lovely. Having a bug reported to you in 2015, and acknowledged, that makes software crash and not fixing it.

 

For NetBeans (still one of the major IDEs) and related stuff like GlassFish, this is too true (a workaround is in the Solution steps) below: [WayBack] Bug 251538 – Your Installer is Creating Invalid Data for the NoModify DWORD Key which crashes enumeration of the Uninstall Key in at least PowerShell, and copied to [WayBack] [NETBEANS-2523] Netbeans 64-bit creates invalid nomodify value in windows registry for years – ASF JIRA.

This one appears for instance when running choco install --yes jre8 (but is certainly not limited to it) as it inspects uninstall registry values which have been corrupted and resulted into [WayBack] “Specified cast is not valid” on jre8 upgrade · Issue #18 · proudcanadianeh/ChocoPackages · GitHub.

Anyway: back to the NoModify issue:

phansson 2015-06-23 13:35:00 UTC
Yep, I can see this problem as well. I believe the problem (bug) has indeed always existed.

What happens is that someone (in this case NetBeans Installer) has put an 8-byte value into a Registry field that should only contain a 4-byte value. DWORDs are 4-byte.

If you use Registry Editor you can clearly see the problem if you look at something NBI has installed. You must look under either
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall (64-bit installers) or HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall (32-bit installers). For some reason I don't see the problem for those NBI applications installed with a 32-bit installer, meaning the stuff in HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall. This can probably be explained when you read the next bit.

NBI actually sets a number of Registry key values but all of them are strings, with the exception of NoModify value. As far as I know this value already defaults to true (=1) if not present so the fact that Windows cannot interpret what NBI has put into the Registry does not have much effect .... until all other kinds of tools will start to explain as you've encountered.

So, what's the problem?  As far as I can see this is really just a very simple bug. In the NBI project (NetBeans Platform source) you have a file called jni_WindowsRegistry.c which defines various JNI methods that can then be used from within Java. One of these is called 'set32BitValue0(....)'.

It looks like this:

JNIEXPORT void JNICALL Java_org_netbeans_installer_utils_system_windows_WindowsRegistry_set32BitValue0(JNIEnv *jEnv, jobject jObject, jint jMode, jint jSection, jstring jKey, jstring jName, jint jValue) {
    unsigned short*  key       = getWideChars(jEnv, jKey);
    unsigned short*  name      = getWideChars(jEnv, jName);
    DWORD  dword     = (DWORD) jValue;
    LPBYTE byteValue = (LPBYTE) &dword;
    
    if (!setValue(getMode(jMode),getHKEY(jSection), key, name, REG_DWORD, byteValue, sizeof(name), 0)) {
        throwException(jEnv, "Cannot set value");
    }
    
    FREE(key);
    FREE(name);
}

One of the parameters passed to the setValue() function is the size (bytes) of the value. Unfortunately whoever made this has made a blunder by using 'sizeof(name)' for that parameter. It should have been the size of the value, not the size of the name, meaning sizeof(dword) or just a hard-coded value of 4.  Just imagine what sizeof(name) will give you if name happens to be 'NoModify'. Yep, that's right: It will be 8.

As I said, I believe this blunder has been in the code from the very beginning. It just hasn't had much effect until now.
Comment 3phansson 2015-06-24 22:12:06 UTC
See https://bitbucket.org/phansson/nbi-native-jnilib-windows
for a fix to this problem. 

Honestly the sole reason why that project exists was that I had to have this problem fixed as our corporate customers were complaining about our software "messing up their Registry" and we could not wait for NetBeans team to fix the problem.
Comment 4oldium 2017-03-03 21:28:13 UTC
Any update on this? I lost 1 hour finding why the Get-ItemProperty of Chocolatey failed and found this. Then I remembered that I had the same issue one year ago...

This issue is now 2 years old, the fix is a one-liner. Is there any plan to fix this or (I am just curious) is Netbeans project dead?
Comment 5scott.fagg 2018-04-27 03:13:04 UTC
We encounter this too. Machines with Netbeans installed on our network often encounter issues when IT roll out software installs. Fix has been to remove and recreate the offending key.

If this has been known since 2015, is there any intention of fixing it ?

I encountered it in 2019, when switching my JRE installations to become chocolatey based.

Solution steps

  1. Run the script mentioned in [WayBack] powershell – How to resolve “ERROR: Specified cast is not valid.” error during installation? – Super User:

    Run the below:

    Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | % { write-host "Key Name:" $_.PSChildName }
    

    This should return some results, then, will return the Specified cast error. The error will occur on the key harboring the invalid subkey.

  2. Then inspect the keys after that in regedit, and watch for any value of type REG_DWORD with a value (invalid DWORD (32-bit) value) (usually named NoModify
  3. Note those keys, and find them in appwiz.cpl
  4. Uninstall the accompanying software

On my systems

Delete the below pieces of crap.

Then run choco install --yes jre8 again.

  • Glassfish

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\nbi-glassfish-mod-3.1.43.0.0

  • NetBeans IDE

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\nbi-nb-base-7.0.0.0.0

Luckily, the NetBeans uninstaller can uninstall GlassFish at the same time:

Do not re-install, as they re-insert the corrupt data.

–jeroen

Posted in Development, Java, Java Platform, Software Development | Leave a Comment »

Delphi object instance lifetime demo; do not use AfterConstruction as a poor-mans way to work around non-virtual constructor or undetermined Create hierarchy calls

Posted by jpluimers on 2021/03/23

I think using AfterConstruction is a poor man’s solution that you should only use in exceptional cases, as it is:

  • called only after the last constructor in the chain is called.
  • called outside of the constructor chain (i.e. exceptions in it will not automatically call the destructor chain, nor BeforeDestruction)
  • meant to add any initialization code that requires a fully created object instance.

There were quite a few sites I  visited that were using AfterConstruction. Usage roughly falls into two cases:

  • Virtually all of their usage was distrusting all Create call chains to be called properly.

    Introducing a new AfterConstruction call chain does not work around this problem.

    In fact it adds just another problem of equal magnitude: a new call chain with the same trust on calling the inheritance chain.

  • Some teams use it as a replacement for a virtual constructor, or as a safeguard for developers calling the non-virtual constructor.

    That kind of AfterConstruction usage now introduces a second call hierarchy, making the code more complex, to circumvent a problem you can easily solve:

    1. introduce a virtual Create constructor in a base class
    2. have that constructor set a field to ensure it is called
    3. check that field at appropriate places, for instance in the Destroy destructor (see example below)

Destruction is important too

A surprising thing in many code bases, is that far less attention is paid to destruction.

Of the above sites, many classes had AfterConstruction. Very few of those had a BeforeDestruction counterpart, though a lot of them should have had one.

In the same light, I see many places where a destructor Destroy never got implemented, leading to all sorts of de-initialisation problems. The easiest problems they can cause are memory leaks, which are usually highly visible. Harder problems are for instance handles that are kept open.

Note that raised Exception instances are normally destroyed in the exception handling.

Finally, a lot of destructor and BeforeDestruction code is very sloppy at handling exceptional cases: not just handling exceptions themselves, but also handling partially initialised instances.

It pays to write unit tests for these cases, as it will save you from surprises.

Execution order

Two small examples in one lifetime demo.

Output

Without raising exceptions:
Create(AConstructorBehaviour = NoExceptionInConstructor)
AfterConstruction
BeforeDestruction
Destroy; FAfterConstructionWasCalled = True;
FreeInstance

With raising exception in constructor:
Create(AConstructorBehaviour = RaiseExceptionInConstructor)
Destroy; FAfterConstructionWasCalled = False;
FreeInstance

With raising exception in AfterConstruction:
Create(AConstructorBehaviour = NoExceptionInConstructor)
AfterConstruction
BeforeDestruction
Destroy; FAfterConstructionWasCalled = True;
FreeInstance
Exception: Error Message

Note the second part of the output does not call AfterConstruction nor BeforeDestruction. This is because when construction fails, the destructor is being called: a Delphi language feature that few people know about as on-line documentation is very hard in html documentation [WayBack] Delphi Language Guide, topic [WayBack] Classes and Objects, subtopic [WayBack] Methods: Constructors:

If an exception is raised during execution of a constructor that was invoked on a class reference, the Destroy destructor is automatically called to destroy the unfinished object.

That – very easy to overlook – one little sentence without any example is all to it, that – as of Delphi 10.1 Berlin – moved to [Archive.is] Methods (Delphi) – RAD Studio: Constructors.

A more elaborate part was put in the html documentation of RAD Studio 2010 C++ documentation subtopic “Object Destruction” quoted below.

Raising exceptions in constuctors

Given this class hierarchy:

type
  A = class
  end;
  B = class(A)
  end;
  C = class(B)
  end;

[Archive.is] Object Destruction – RAD Studio, limited to only the Pascal bits, then is like this:

Consider the case where an exception is raised in the constructor of class B when constructing an instance of C. What results in .. Object Pascal …is described here:

  • In Object Pascal, only the instantiated class destructor is called automatically. This is the destructor for C. As with constructors, it is entirely the programmer’s responsibility to call inherited in destructors. In this example, if we assume all of the destructors call inherited, then the destructors for C, B, and A are called in that order. Moreover, whether or not inherited was already called in B’s constructor before the exception occurred, A’s destructor is called because inherited was called in B’s destructor. Calling the destructor for A is independent of whether its constructor was actually called. More importantly, because it is common for constructors to call inherited immediately, the destructor for C is called whether or not the body of its constructor was completely executed.

The oldest (PDF) documentation I could find mentioning this is [WayBack] CB6_DevelopersGuide_EN.pdf (C++ Builder 6: Developer’s Guide – Documentation).

It still strikes me as odd that such an important Delphi language feature is only documented in the C++ product line.

Luckily others stepped into this void, all found through delphi raise in constructor calls destructor – Google Search:

There is also on-line information that puts you on the wrong foot:

[WayBack] Exceptions in Constructor and or AfterConstruction ? – delphi

But why than is BeforeDestruction not being call automatically when the the
exception is raised in AfterConstruction?

The above output shows this last observation is clearly wrong.

Detecting if methods got called

The second part of the output also shows you that you can detect the condition that AfterConstruction was indeed called (or in fact any method was called) from the Destroy (or any other method).

The code below shows that this is very easy to do.

Code

program ExceptionInConstructorConsoleProject;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  System.Rtti;

type
  TConstructorBehaviour = (RaiseExceptionInConstructor, NoExceptionInConstructor);
  TAfterConstructionBehaviour =  (RaiseExceptionInAfterConstruction, NoExceptionInConstructorAfterConstruction);
  TExceptionInConstructorClass = class(TObject)
  strict private
    FAfterConstructionWasCalled: Boolean;
    FAfterConstructionBehaviour: TAfterConstructionBehaviour;
  public
    constructor Create(const AConstructorBehaviour: TConstructorBehaviour; const AAfterConstructionBehaviour: TAfterConstructionBehaviour);
    destructor Destroy(); override;
    procedure AfterConstruction(); override;
    procedure BeforeDestruction(); override;
  end;

constructor TExceptionInConstructorClass.Create(const AConstructorBehaviour: TConstructorBehaviour);
begin
  Writeln(Format('Create(AConstructorBehaviour = %s)', [TRttiEnumerationType.GetName(AConstructorBehaviour)]));
  inherited Create();
  FAfterConstructionWasCalled := False;
  FAfterConstructionBehaviour := AAfterConstructionBehaviour;
  if AConstructorBehaviour = RaiseExceptionInConstructor then
    raise Exception.Create('Error Message');
end;

destructor TExceptionInConstructorClass.Destroy();
begin
  Writeln(Format('Destroy; FAfterConstructionWasCalled = %s;', [TRttiEnumerationType.GetName<Boolean>(FAfterConstructionWasCalled)]));
  inherited Destroy();
end;

procedure TExceptionInConstructorClass.AfterConstruction();
begin
  Writeln('AfterConstruction');
  inherited AfterConstruction();
  if FAfterConstructionBehaviour = RaiseExceptionInAfterConstruction then
    raise Exception.Create('Error Message');
end;

procedure TExceptionInConstructorClass.BeforeDestruction();
begin
  Writeln('BeforeDestruction');
  inherited BeforeDestruction();
end;

procedure TExceptionInConstructorClass.FreeInstance();
begin
  Writeln('FreeInstance');
  inherited FreeInstance();
end;
begin
  try
    Writeln('Without raising exceptions:');
    with TExceptionInConstructorClass.Create(NoExceptionInConstructor, NoExceptionInConstructorAfterConstruction) do
      Free();
    Writeln;
    Writeln('With raising exception in constructor:');
    try
      TExceptionInConstructorClass.Create(RaiseExceptionInConstructor, NoExceptionInConstructorAfterConstruction);
    finally
      Writeln;
      Writeln('With raising exception in AfterConstruction:');
      TExceptionInConstructorClass.Create(NoExceptionInConstructor, RaiseExceptionInAfterConstruction);
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Statistics

In the Delphi source directory (RTL + FMX + VCL + more), you see this count:

  • constructor Create: ~5000 occurrences
  • destructor Destroy: ~2300 occurrences
  • procedure AfterConstruction: ~400 occurrences of which ~100 relevant, as there are ~300 in unit FMX.DEA.Schema to perform XML schema setup right after the constructor is run.
  • procedure BeforeDestruction: ~25 occurrences.

In % ratios:

  • Create: 100%
  • Destroy: ~45%
  • AfterConstruction: 2%
  • BeforeDestruction: 0.5%

Related

The above were centered around these pieces of Delphi documentation:

If you want to dig deeper into the various methods involved in allocation, initialisation, construction, deconstruction, and de-allocation, then remember that in the Win32 realm (which is the central target for most Delphi developers) not much has changed since Delphi 2007.

Outside that realm, things do have changed. For that, read this great book, that taught me quite a few things: [WayBack] Delphi Memory Management eBook .

Besides the eBook, you can also get it as

  • Paperback: 377 pages
  • Publisher: CreateSpace Independent Publishing Platform (June 24, 2018)
  • Language: English
  • ISBN-10: 1721654909
  • ISBN-13: 978-1721654901

These are the relevant adapted from the Delphi 2007 [WayBack] TObject Members:

WayBack Declaration Name Description
[WayBack]
procedure AfterConstruction; virtual;
AfterConstruction Responds after the last constructor has executed.
[WayBack]
procedure BeforeDestruction; virtual;
BeforeDestruction Responds before the first destructor executes.
[WayBack]
procedure CleanupInstance;
CleanupInstance Performs finalization on long strings, variants, and interface variables within a class.
[WayBack]
constructor Create;
Create Constructs an object and initializes its data before the object is first used.
[WayBack]
destructor Destroy; virtual;
Destroy Disposes of an object instance.
[WayBack]
procedure Free;
Free Destroys an object and frees its associated memory, if necessary.
[WayBack]
procedure FreeInstance; virtual;
FreeInstance Deallocates memory allocated by a previous call to the System::TObject::NewInstance method.
[WayBack]
class function InitInstance(Instance: Pointer): TObject;
InitInstance Initializes a newly allocated object instance to all zeros and initializes the instance’s virtual method table pointer.
[WayBack]
class function InstanceSize: Longint;
InstanceSize Returns the size in bytes of each instance of the object type.
[WayBack]
class function NewInstance: TObject; virtual;
NewInstance Allocates memory for an instance of an object type and returns a pointer to that new instance.

Combinining NewInstance with FeeInstance can be useful in for instance these cases:

I wish the TAbstractWorkerData was more appropriately documented, as some really interesting stuff is going on in it.

–jeroen

Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development, Undocumented Delphi | 1 Comment »

Some links with notes on WoonVeilig/Egardia security system communications, protocols and support by 3rd party home automation apps

Posted by jpluimers on 2021/03/23

Security issues for older models (mainly GATE01 and WV-1716 systems; which used a lot of Climax components):

A more recent security review:

Physical security is important too; ensure the system is in an enclosed closet, powered by a UPS and your communication lines are secured as well: [WayBack] Manipulationen an Alarmanlagen verhindern – Smarthomewiki

Dutch links on the hardware connections and protocols used:

More recent information:

API usage:

More subdomains (in 2019) via:

–jeroen

Read the rest of this entry »

Posted in Communications Development, Development, Power User, Security, Software Development | Leave a Comment »

 
%d bloggers like this: