public bool Handle(OffRegKey key) { // TODO: exceptions thrown from this function should use STATUS_* error codes set // instead of ERROR_* string name = key.Identity.GetSystemPath(); KeyInfo info = key.QueryInfo(); // TODO: either test the following error-prone code with offsets thoroughly // or replace it with safer alternative code int offset = 0; switch (KeyInformationClass_) { case Win32Api.KeyInformationClass.KeyBasicInformation: ResultLength_ = unchecked((uint)(16 + sizeof(char) * name.Length)); if (Length_ < ResultLength_) { throw Win32Exception.Create((int)Win32Api.Status.STATUS_BUFFER_TOO_SMALL); } if (KeyInformation_ != IntPtr.Zero) { Marshal.StructureToPtr(info.LastWriteTime, KeyInformation_, false); offset += 8; Marshal.WriteInt32(KeyInformation_, offset, 0); offset += 4; Marshal.WriteInt32(KeyInformation_, offset, sizeof(char) * name.Length); offset += 4; PInvokeHelper.CopyStringUni(name, (IntPtr)((Int64)KeyInformation_ + offset), name.Length); } return true; case Win32Api.KeyInformationClass.KeyNodeInformation: ResultLength_ = unchecked((uint)(24 + sizeof(char) * (name.Length + info.Class.Length))); if (Length_ < ResultLength_) { throw Win32Exception.Create((int)Win32Api.Status.STATUS_BUFFER_TOO_SMALL); } if (KeyInformation_ != IntPtr.Zero) { // TODO: fill the parts of structures w/o strings using // C# structures (until now I don't know solution for strings, but // at least all other fields will be set carefully) // do this throughout the function Marshal.StructureToPtr(info.LastWriteTime, KeyInformation_, false); offset += 8; Marshal.WriteInt32(KeyInformation_, offset, 0); offset += 4; Marshal.WriteInt32(KeyInformation_, offset, 24 + sizeof(char) * name.Length); offset += 4; Marshal.WriteInt32(KeyInformation_, offset, sizeof(char) * info.Class.Length); offset += 4; Marshal.WriteInt32(KeyInformation_, offset, sizeof(char) * name.Length); offset += 4; PInvokeHelper.CopyStringUni(name, (IntPtr)((Int64)KeyInformation_ + offset), name.Length); offset += name.Length * sizeof(char); PInvokeHelper.CopyStringUni(info.Class, (IntPtr)((Int64)KeyInformation_ + offset), info.Class.Length); } return true; case Win32Api.KeyInformationClass.KeyFullInformation: ResultLength_ = unchecked((uint)(44 + sizeof(char) * (info.Class.Length))); if (Length_ < ResultLength_) { throw Win32Exception.Create((int)Win32Api.Status.STATUS_BUFFER_TOO_SMALL); } if (KeyInformation_ != IntPtr.Zero) { Marshal.StructureToPtr(info.LastWriteTime, KeyInformation_, false); offset += 8; Marshal.WriteInt32(KeyInformation_, offset, 0); offset += 4; Marshal.WriteInt32(KeyInformation_, offset, 44); offset += 4; Marshal.WriteInt32(KeyInformation_, offset, sizeof(char) * info.Class.Length); offset += 4; Marshal.WriteInt32(KeyInformation_, offset, unchecked((int)info.SubKeysNumber)); offset += 4; Marshal.WriteInt32(KeyInformation_, offset, unchecked((int)info.MaxSubKeyLength)); offset += 4; Marshal.WriteInt32(KeyInformation_, offset, unchecked((int)info.MaxClassLength)); offset += 4; Marshal.WriteInt32(KeyInformation_, offset, unchecked((int)info.ValuesNumber)); offset += 4; Marshal.WriteInt32(KeyInformation_, offset, unchecked((int)info.MaxValueNameLength)); offset += 4; Marshal.WriteInt32(KeyInformation_, offset, unchecked((int)info.MaxValueLength)); offset += 4; PInvokeHelper.CopyStringUni(info.Class, (IntPtr)((Int64)KeyInformation_ + offset), info.Class.Length); } return true; case Win32Api.KeyInformationClass.KeyNameInformation: ResultLength_ = unchecked((uint)(4 + sizeof(char) * name.Length)); if (Length_ < ResultLength_) { throw Win32Exception.Create((int)Win32Api.Status.STATUS_BUFFER_TOO_SMALL); } if (KeyInformation_ != IntPtr.Zero) { Marshal.WriteInt32(KeyInformation_, sizeof(char) * name.Length); offset += 4; PInvokeHelper.CopyStringUni(name, (IntPtr)((Int64)KeyInformation_ + offset), name.Length); } return true; case Win32Api.KeyInformationClass.KeyCachedInformation: ResultLength_ = 36; if (Length_ < ResultLength_) { throw Win32Exception.Create((int)Win32Api.Status.STATUS_BUFFER_TOO_SMALL); } if (KeyInformation_ != IntPtr.Zero) { Marshal.StructureToPtr(info.LastWriteTime, KeyInformation_, false); offset += 8; Marshal.WriteInt32(KeyInformation_, offset, 0); offset += 4; Marshal.WriteInt32(KeyInformation_, offset, unchecked((int)info.SubKeysNumber)); offset += 4; Marshal.WriteInt32(KeyInformation_, offset, unchecked((int)info.MaxSubKeyLength)); offset += 4; Marshal.WriteInt32(KeyInformation_, offset, unchecked((int)info.ValuesNumber)); offset += 4; Marshal.WriteInt32(KeyInformation_, offset, unchecked((int)info.MaxValueNameLength)); offset += 4; Marshal.WriteInt32(KeyInformation_, offset, unchecked((int)info.MaxValueLength)); offset += 4; Marshal.WriteInt32(KeyInformation_, offset, name.Length); } return true; case Win32Api.KeyInformationClass.KeyFlagsInformation: // Reserved break; case Win32Api.KeyInformationClass.KeyVirtualizationInformation: // Not implemented break; case Win32Api.KeyInformationClass.KeyHandleTagsInformation: // Reserved break; } return false; }