你给出的sysinternals链接很好地描述了这个理论:

Win32 API字符串中的“

”被解释为以NULL结尾的ANSI(8位)或宽字符(16位)字符串。在Native API中,名称被计算为Unicode (16位)字符串。虽然这种区别通常并不重要,但它留下了一个有趣的情况:有一类名称可以使用Native API引用,但不能使用Win32 API描述。

因此,对于win32的RegCreateKeyW(),如果您试图给它一个类似"Foo\0Bar“的键名,它将只使用"Foo\0",而看不到其余的。

使用原生API等效项,比如NtCreateKey,必须同时提供字符串缓冲区和长度(作为OBJECT_ATTRIBUTES参数的UNICODE_STRING成员)。因此,它将愉快地使用并创建一个名为"Foo\0Bar“的键。

Regedit或任何其他使用win32应用程序接口的程序将无法打开此密钥。当他们枚举父级时,他们只会得到以null结尾的名字"Foo\0",这个名字实际上并不存在。因此,如果您在regedit中单击"Foo“,它将抛出一个错误,因为它的RegOpenKey("Foo")调用失败。

要查找、打开和删除这些文件,您需要转到本机api。

第一步是将函数声明和支持的参数类型转换为delphi,并从ntdll.dll动态加载函数。

下面是一些可以开始使用的转换:

代码语言:javascript复制type

NTSTATUS = Longint;

PLARGE_INTEGER = ^LARGE_INTEGER;

USHORT = Word;

UNICODE_STRING = record

Length: WORD;

MaximumLength: WORD;

Buffer: PWideChar;

end;

PUNICODE_STRING = ^UNICODE_STRING;

OBJECT_ATTRIBUTES = record

Length: ULONG;

RootDirectory: THandle;

ObjectName: PUNICODE_STRING;

Attributes: ULONG;

SecurityDescriptor: Pointer;

SecurityQualityOfService: Pointer;

end;

POBJECT_ATTRIBUTES = ^OBJECT_ATTRIBUTES;

// function prototypes

TNtCreateKey = function(KeyHandle : PHANDLE;

DesiredAccess: ACCESS_MASK;

ObjectAttributes: POBJECT_ATTRIBUTES;

TitleIndex: ULONG;

ClassType: PUNICODE_STRING;

CreateOptions: ULONG;

Disposition: PULONG

): NTSTATUS; stdcall;

TNtDeleteKey = function(KeyHandle: THANDLE): NTSTATUS; stdcall;还有一个旧的article over at the codeproject,它有更多的示例代码(C++)和解释,可以帮助您完成剩下的工作。