{"record":{"id":"17c77115c9784448","repo":"HandyOrg/HandyControl","slug":"wrote-an-incorrect-number-of-bytes-interopvalues","errorCode":null,"errorMessage":"Wrote an incorrect number of bytes","messagePattern":"Wrote an incorrect number of bytes","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/Shared/HandyControl_Shared/Tools/Interop/InteropValues.cs","lineNumber":882,"sourceCode":"\n        public virtual long CopyTo(IStream pstm, long cb, long[] pcbRead)\n        {\n            const int bufsize = 4096; // one page\n            var buffer = Marshal.AllocHGlobal(bufsize);\n            if (buffer == IntPtr.Zero) throw new OutOfMemoryException();\n            long written = 0;\n\n            try\n            {\n                while (written < cb)\n                {\n                    var toRead = bufsize;\n                    if (written + toRead > cb) toRead = (int) (cb - written);\n                    var read = Read(buffer, toRead);\n                    if (read == 0) break;\n                    if (pstm.Write(buffer, read) != read)\n                    {\n                        throw EFail(\"Wrote an incorrect number of bytes\");\n                    }\n                    written += read;\n                }\n            }\n            finally\n            {\n                Marshal.FreeHGlobal(buffer);\n            }\n            if (pcbRead != null && pcbRead.Length > 0)\n            {\n                pcbRead[0] = written;\n            }\n\n            return written;\n        }\n\n        public virtual Stream GetDataStream() => DataStream;\n","sourceCodeStart":864,"sourceCodeEnd":900,"githubUrl":"https://github.com/HandyOrg/HandyControl/blob/2c0875ebd67326e0c67282967e3e809c69282fee/src/Shared/HandyControl_Shared/Tools/Interop/InteropValues.cs#L864-L900","documentation":"Identical EFail throw inside HandyControl's InteropValues (the same IStream CopyTo logic embedded in the interop helper): when pstm.Write returns a count different from the bytes read, the stream wrapper declares the write failed and throws \"Wrote an incorrect number of bytes\". It guards against native IStream implementations that do not honor the COM contract of writing all requested bytes and reporting the count.","triggerScenarios":"Same as GPStream: CopyTo loop calls Read then pstm.Write; any Write return value != read (short write, 0, or an error HRESULT already converted) triggers the throw at the call site in InteropValues.cs:882.","commonSituations":"Using HandyControl interop helpers with clipboard/OLE streams (CF_HDROP / IStream from native code) where the native Write fails partway — often due to the source stream being released early, insufficient memory, or a custom IStream stub that returns the wrong count.","solutions":["Verify the native side correctly implements IStream.Write and returns the actual bytes written.","Ensure the COM stream's lifetime is managed correctly (release it only after copy completes; check Marshal.ReleaseComObject usage).","Retry the operation with a freshly obtained stream (re-copy clipboard data or re-open the storage).","Catch the failure in calling code and fall back to a managed stream path (e.g. copy via MemoryStream first)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Validate the interop stream before use:\nif (pstm == null) throw new InvalidOperationException(\"IStream is null\");\n// If obtainable, confirm STATSTG cbSize > 0 via IStream.Stat before copying.","typeGuard":"static bool HasComStream(object comObj) =>\n    comObj != null && Marshal.IsComObject(comObj);","tryCatchPattern":"try\n{\n    // interop copy path using InteropValues stream wrapper\n}\ncatch (Exception ex) when (ex.Message == \"Wrote an incorrect number of bytes\")\n{\n    // re-fetch the stream source (e.g. re-read clipboard data) and retry once\n}","preventionTips":["Release COM streams only after the copy operation finishes.","Re-acquire clipboard/OLE stream data instead of caching the IStream across calls.","Log and surface HRESULT details when short writes occur to identify the faulty native implementation.","Prefer copying through a managed MemoryStream when the native stream is of unknown quality."],"tags":["csharp","com-interop","istream","clipboard","stream"],"backgroundTag":"internal-invariant-violation","analyzedSha":"2c0875ebd67326e0c67282967e3e809c69282fee","analyzedAt":"2026-09-14T14:45:29.754Z","contentChangedAt":"2026-09-14T14:45:29.754Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}