Cleanup VARIANT marshalling and convert to managed - #102498

Merged
AaronRobinsonMSFT merged 48 commits into
dotnet:mainfrom
huoyaoyuan:variant-2
Aug 28, 2024
Merged

Cleanup VARIANT marshalling and convert to managed#102498
AaronRobinsonMSFT merged 48 commits into
dotnet:mainfrom
huoyaoyuan:variant-2

Conversation

@huoyaoyuan

Copy link
Copy Markdown
Member

Cleans up the managed Variant struct used as an intermediate value.

Basically, folds MarshalHelperConvertObjectToVariant with MarshalOleVariantForComVariant, MarshalHelperConvertVariantToObject and MarshalHelperCastVariant with MarshalComVariantForOleVariant.

Tests were first written and tested on main.

Array and record marshalling are still kept native. VT_ARRAY marshalling looks sharing many logic with non-variant marshalling.

@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label May 21, 2024
Comment threadsrc/coreclr/System.Private.CoreLib/src/System/Variant.cs
Comment threadsrc/coreclr/vm/olevariant.cpp Outdated
Comment threadsrc/coreclr/vm/olevariant.cpp Outdated
Comment on lines +352 to 356
case VarEnum.VT_RECORD:
MarshalHelperConvertObjectToVariant(pValue, out v);
if (v.VarType != VarEnum.VT_RECORD)
throw new InvalidCastException(SR.InvalidCast_CannotCoerceByRefVariant);
break;

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to restore the behavior here, and relying on the location to be cleaned up by RAII at native side.
Is there any better option for this?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the previous behavior in this case? I'm not following the issue being hit here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any destructors in MarshalOleRefVariantForObject. Is that where you are talking about?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously in MarshalOleRefVariantForObject, if SafeVariantChangeType fails, would the data (potentially BSTR or something else) in vtmp be leaked? SafeVariantClear won't be called in throwing path.

I've concluded that SafeVariantChangeType is unnecessary and will always fail. The content of the VARIANT should be cleared at managed side in failing path.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

@AaronRobinsonMSFT Can you answer remaining questions in this PR?

The concern is about cleanup in exceptional cases with partial result. When taking a ref at managed side, RAII at native side may take care of the cleanup.
I still want to keep the current implementation and shape as possible.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

Is there anything remaining in this? I think we should aim to merge this to avoid more conflicts with other refactoring.

@AaronRobinsonMSFT

Copy link
Copy Markdown
Member

Thanks @huoyaoyuan. Appreciate the work here. I would ask that you please avoid converting more of the legacy COM interop code. The interop team is slowing making out way through it and it is both a learning exercise for us to understand what we support and how best to integrate it into the current code base.

It is doubly costly for us when there is inevtiably a missed compat case and we need to track it down. It is best left for the interop team to port over. I appreciate the added tests, but many of the questions you've asked are only answerable as we slowly detangle/understand the existing code.

Again, we do appreciate this PR, but we would prefer porting more commonly used code paths that have less impact to legacy and fragile .NET code bases.

@AaronRobinsonMSFT Can you answer remaining questions in this PR?

The best way to address these issue is through additional testing. These code paths are very old and subtle in many ways. I will try and do one more pass soon so we can get this specific PR in.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

No problem. I was assuming that you have enough knowledge to answer all the questions raised. But apparently you may need to spend similar effort than me to understand the scenarios, or even more effort to be responsible for every corner cases.

My interest in this was originally raised up when learning the types evolved with interop. Currently I have no extra work beyond this.

@AaronRobinsonMSFTAaronRobinsonMSFT left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@AaronRobinsonMSFT
AaronRobinsonMSFT merged commit c1a9f26 into dotnet:mainAug 28, 2024
@huoyaoyuan
huoyaoyuan deleted the variant-2 branch August 28, 2024 02:43
jtschuster pushed a commit to jtschuster/runtime that referenced this pull request Sep 17, 2024
* Handle simple cases of MarshalComVariantForOleVariant
* Pseudo code for MarshalOleVariantForComVariant
* Complete and setup managed call for MarshalObjectForOleVariant
* Setup MarshalHelperConvertObjectToVariant except record
* Setup MarshalHelperCastVariant
* Cleanup Variant struct and FCall
* Handle record case
* Cleanup VariantOleToCom/VariantComToOle routines
* Remove VariantData definition at unmanaged side
* Eliminate a dead branch for ref
* Remove CVTypes in native
* Share GetComIPFromObjectRef
* Add tests for managed to native side
* Add test for native to managed side
* Add test for byref returning to BYREF
* Fix BYREF handling
* Fix array marshalling
* Fix record marshalling
* Fix VT_VARIANT case
* Cleanup and fix IUnknown case
* Add more test for VT_UNKNOWN
* Cleanup for VT_VARIANT
* Cleanup SR and comment
* Fix contract in GetTypeHandleForVarType
* Move VariantChangeTypeEx to coreclr
* Add unmanaged fast path for (U)Int64
* Make ComVariant immutable
* Add GCPROTECT in ConvertSystemColorToOleColor
* Fix variant init
* Fix BYREF|EMPTY
* Initialize ComVariant
* Move GCPROTECT to the QCall
* Pass UnknownWrapper through SetFieldsObject
* Apply suggestions from code review
Co-authored-by: Aaron Robinson <arobins@microsoft.com>
* Suggestions at native side
* Rename ComIP
* Add comments for ConvertWrappedObject
* Try convert to RECORD for all cases
* Dispose Variant on failure
* Update formatting
* Fix NO_MAPPING definition
---------
Co-authored-by: Aaron Robinson <arobins@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Sep 28, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-Interop-coreclrcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@huoyaoyuan@AaronRobinsonMSFT@jkoritzinsky
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Cleanup VARIANT marshalling and convert to managed - #102498

Merged
AaronRobinsonMSFT merged 48 commits into
dotnet:mainfrom
huoyaoyuan:variant-2
Aug 28, 2024
Merged

Cleanup VARIANT marshalling and convert to managed#102498
AaronRobinsonMSFT merged 48 commits into
dotnet:mainfrom
huoyaoyuan:variant-2

Conversation

@huoyaoyuan

Copy link
Copy Markdown
Member

Cleans up the managed Variant struct used as an intermediate value.

Basically, folds MarshalHelperConvertObjectToVariant with MarshalOleVariantForComVariant, MarshalHelperConvertVariantToObject and MarshalHelperCastVariant with MarshalComVariantForOleVariant.

Tests were first written and tested on main.

Array and record marshalling are still kept native. VT_ARRAY marshalling looks sharing many logic with non-variant marshalling.

@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label May 21, 2024
Comment threadsrc/coreclr/System.Private.CoreLib/src/System/Variant.cs
Comment threadsrc/coreclr/vm/olevariant.cpp Outdated
Comment threadsrc/coreclr/vm/olevariant.cpp Outdated
Comment on lines +352 to 356
case VarEnum.VT_RECORD:
MarshalHelperConvertObjectToVariant(pValue, out v);
if (v.VarType != VarEnum.VT_RECORD)
throw new InvalidCastException(SR.InvalidCast_CannotCoerceByRefVariant);
break;

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to restore the behavior here, and relying on the location to be cleaned up by RAII at native side.
Is there any better option for this?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the previous behavior in this case? I'm not following the issue being hit here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any destructors in MarshalOleRefVariantForObject. Is that where you are talking about?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously in MarshalOleRefVariantForObject, if SafeVariantChangeType fails, would the data (potentially BSTR or something else) in vtmp be leaked? SafeVariantClear won't be called in throwing path.

I've concluded that SafeVariantChangeType is unnecessary and will always fail. The content of the VARIANT should be cleared at managed side in failing path.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

@AaronRobinsonMSFT Can you answer remaining questions in this PR?

The concern is about cleanup in exceptional cases with partial result. When taking a ref at managed side, RAII at native side may take care of the cleanup.
I still want to keep the current implementation and shape as possible.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

Is there anything remaining in this? I think we should aim to merge this to avoid more conflicts with other refactoring.

@AaronRobinsonMSFT

Copy link
Copy Markdown
Member

Thanks @huoyaoyuan. Appreciate the work here. I would ask that you please avoid converting more of the legacy COM interop code. The interop team is slowing making out way through it and it is both a learning exercise for us to understand what we support and how best to integrate it into the current code base.

It is doubly costly for us when there is inevtiably a missed compat case and we need to track it down. It is best left for the interop team to port over. I appreciate the added tests, but many of the questions you've asked are only answerable as we slowly detangle/understand the existing code.

Again, we do appreciate this PR, but we would prefer porting more commonly used code paths that have less impact to legacy and fragile .NET code bases.

@AaronRobinsonMSFT Can you answer remaining questions in this PR?

The best way to address these issue is through additional testing. These code paths are very old and subtle in many ways. I will try and do one more pass soon so we can get this specific PR in.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

No problem. I was assuming that you have enough knowledge to answer all the questions raised. But apparently you may need to spend similar effort than me to understand the scenarios, or even more effort to be responsible for every corner cases.

My interest in this was originally raised up when learning the types evolved with interop. Currently I have no extra work beyond this.

@AaronRobinsonMSFTAaronRobinsonMSFT left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@AaronRobinsonMSFT
AaronRobinsonMSFT merged commit c1a9f26 into dotnet:mainAug 28, 2024
@huoyaoyuan
huoyaoyuan deleted the variant-2 branch August 28, 2024 02:43
jtschuster pushed a commit to jtschuster/runtime that referenced this pull request Sep 17, 2024
* Handle simple cases of MarshalComVariantForOleVariant
* Pseudo code for MarshalOleVariantForComVariant
* Complete and setup managed call for MarshalObjectForOleVariant
* Setup MarshalHelperConvertObjectToVariant except record
* Setup MarshalHelperCastVariant
* Cleanup Variant struct and FCall
* Handle record case
* Cleanup VariantOleToCom/VariantComToOle routines
* Remove VariantData definition at unmanaged side
* Eliminate a dead branch for ref
* Remove CVTypes in native
* Share GetComIPFromObjectRef
* Add tests for managed to native side
* Add test for native to managed side
* Add test for byref returning to BYREF
* Fix BYREF handling
* Fix array marshalling
* Fix record marshalling
* Fix VT_VARIANT case
* Cleanup and fix IUnknown case
* Add more test for VT_UNKNOWN
* Cleanup for VT_VARIANT
* Cleanup SR and comment
* Fix contract in GetTypeHandleForVarType
* Move VariantChangeTypeEx to coreclr
* Add unmanaged fast path for (U)Int64
* Make ComVariant immutable
* Add GCPROTECT in ConvertSystemColorToOleColor
* Fix variant init
* Fix BYREF|EMPTY
* Initialize ComVariant
* Move GCPROTECT to the QCall
* Pass UnknownWrapper through SetFieldsObject
* Apply suggestions from code review
Co-authored-by: Aaron Robinson <arobins@microsoft.com>
* Suggestions at native side
* Rename ComIP
* Add comments for ConvertWrappedObject
* Try convert to RECORD for all cases
* Dispose Variant on failure
* Update formatting
* Fix NO_MAPPING definition
---------
Co-authored-by: Aaron Robinson <arobins@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Sep 28, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-Interop-coreclrcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@huoyaoyuan@AaronRobinsonMSFT@jkoritzinsky
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Cleanup VARIANT marshalling and convert to managed - #102498

Merged
AaronRobinsonMSFT merged 48 commits into
dotnet:mainfrom
huoyaoyuan:variant-2
Aug 28, 2024
Merged

Cleanup VARIANT marshalling and convert to managed#102498
AaronRobinsonMSFT merged 48 commits into
dotnet:mainfrom
huoyaoyuan:variant-2

Conversation

@huoyaoyuan

Copy link
Copy Markdown
Member

Cleans up the managed Variant struct used as an intermediate value.

Basically, folds MarshalHelperConvertObjectToVariant with MarshalOleVariantForComVariant, MarshalHelperConvertVariantToObject and MarshalHelperCastVariant with MarshalComVariantForOleVariant.

Tests were first written and tested on main.

Array and record marshalling are still kept native. VT_ARRAY marshalling looks sharing many logic with non-variant marshalling.

@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label May 21, 2024
Comment threadsrc/coreclr/System.Private.CoreLib/src/System/Variant.cs
Comment threadsrc/coreclr/vm/olevariant.cpp Outdated
Comment threadsrc/coreclr/vm/olevariant.cpp Outdated
Comment on lines +352 to 356
case VarEnum.VT_RECORD:
MarshalHelperConvertObjectToVariant(pValue, out v);
if (v.VarType != VarEnum.VT_RECORD)
throw new InvalidCastException(SR.InvalidCast_CannotCoerceByRefVariant);
break;

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to restore the behavior here, and relying on the location to be cleaned up by RAII at native side.
Is there any better option for this?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the previous behavior in this case? I'm not following the issue being hit here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any destructors in MarshalOleRefVariantForObject. Is that where you are talking about?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously in MarshalOleRefVariantForObject, if SafeVariantChangeType fails, would the data (potentially BSTR or something else) in vtmp be leaked? SafeVariantClear won't be called in throwing path.

I've concluded that SafeVariantChangeType is unnecessary and will always fail. The content of the VARIANT should be cleared at managed side in failing path.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

@AaronRobinsonMSFT Can you answer remaining questions in this PR?

The concern is about cleanup in exceptional cases with partial result. When taking a ref at managed side, RAII at native side may take care of the cleanup.
I still want to keep the current implementation and shape as possible.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

Is there anything remaining in this? I think we should aim to merge this to avoid more conflicts with other refactoring.

@AaronRobinsonMSFT

Copy link
Copy Markdown
Member

Thanks @huoyaoyuan. Appreciate the work here. I would ask that you please avoid converting more of the legacy COM interop code. The interop team is slowing making out way through it and it is both a learning exercise for us to understand what we support and how best to integrate it into the current code base.

It is doubly costly for us when there is inevtiably a missed compat case and we need to track it down. It is best left for the interop team to port over. I appreciate the added tests, but many of the questions you've asked are only answerable as we slowly detangle/understand the existing code.

Again, we do appreciate this PR, but we would prefer porting more commonly used code paths that have less impact to legacy and fragile .NET code bases.

@AaronRobinsonMSFT Can you answer remaining questions in this PR?

The best way to address these issue is through additional testing. These code paths are very old and subtle in many ways. I will try and do one more pass soon so we can get this specific PR in.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

No problem. I was assuming that you have enough knowledge to answer all the questions raised. But apparently you may need to spend similar effort than me to understand the scenarios, or even more effort to be responsible for every corner cases.

My interest in this was originally raised up when learning the types evolved with interop. Currently I have no extra work beyond this.

@AaronRobinsonMSFTAaronRobinsonMSFT left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@AaronRobinsonMSFT
AaronRobinsonMSFT merged commit c1a9f26 into dotnet:mainAug 28, 2024
@huoyaoyuan
huoyaoyuan deleted the variant-2 branch August 28, 2024 02:43
jtschuster pushed a commit to jtschuster/runtime that referenced this pull request Sep 17, 2024
* Handle simple cases of MarshalComVariantForOleVariant
* Pseudo code for MarshalOleVariantForComVariant
* Complete and setup managed call for MarshalObjectForOleVariant
* Setup MarshalHelperConvertObjectToVariant except record
* Setup MarshalHelperCastVariant
* Cleanup Variant struct and FCall
* Handle record case
* Cleanup VariantOleToCom/VariantComToOle routines
* Remove VariantData definition at unmanaged side
* Eliminate a dead branch for ref
* Remove CVTypes in native
* Share GetComIPFromObjectRef
* Add tests for managed to native side
* Add test for native to managed side
* Add test for byref returning to BYREF
* Fix BYREF handling
* Fix array marshalling
* Fix record marshalling
* Fix VT_VARIANT case
* Cleanup and fix IUnknown case
* Add more test for VT_UNKNOWN
* Cleanup for VT_VARIANT
* Cleanup SR and comment
* Fix contract in GetTypeHandleForVarType
* Move VariantChangeTypeEx to coreclr
* Add unmanaged fast path for (U)Int64
* Make ComVariant immutable
* Add GCPROTECT in ConvertSystemColorToOleColor
* Fix variant init
* Fix BYREF|EMPTY
* Initialize ComVariant
* Move GCPROTECT to the QCall
* Pass UnknownWrapper through SetFieldsObject
* Apply suggestions from code review
Co-authored-by: Aaron Robinson <arobins@microsoft.com>
* Suggestions at native side
* Rename ComIP
* Add comments for ConvertWrappedObject
* Try convert to RECORD for all cases
* Dispose Variant on failure
* Update formatting
* Fix NO_MAPPING definition
---------
Co-authored-by: Aaron Robinson <arobins@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Sep 28, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-Interop-coreclrcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@huoyaoyuan@AaronRobinsonMSFT@jkoritzinsky
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Cleanup VARIANT marshalling and convert to managed - #102498

Merged
AaronRobinsonMSFT merged 48 commits into
dotnet:mainfrom
huoyaoyuan:variant-2
Aug 28, 2024
Merged

Cleanup VARIANT marshalling and convert to managed#102498
AaronRobinsonMSFT merged 48 commits into
dotnet:mainfrom
huoyaoyuan:variant-2

Conversation

@huoyaoyuan

Copy link
Copy Markdown
Member

Cleans up the managed Variant struct used as an intermediate value.

Basically, folds MarshalHelperConvertObjectToVariant with MarshalOleVariantForComVariant, MarshalHelperConvertVariantToObject and MarshalHelperCastVariant with MarshalComVariantForOleVariant.

Tests were first written and tested on main.

Array and record marshalling are still kept native. VT_ARRAY marshalling looks sharing many logic with non-variant marshalling.

@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label May 21, 2024
Comment threadsrc/coreclr/System.Private.CoreLib/src/System/Variant.cs
Comment threadsrc/coreclr/vm/olevariant.cpp Outdated
Comment threadsrc/coreclr/vm/olevariant.cpp Outdated
Comment on lines +352 to 356
case VarEnum.VT_RECORD:
MarshalHelperConvertObjectToVariant(pValue, out v);
if (v.VarType != VarEnum.VT_RECORD)
throw new InvalidCastException(SR.InvalidCast_CannotCoerceByRefVariant);
break;

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to restore the behavior here, and relying on the location to be cleaned up by RAII at native side.
Is there any better option for this?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the previous behavior in this case? I'm not following the issue being hit here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any destructors in MarshalOleRefVariantForObject. Is that where you are talking about?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously in MarshalOleRefVariantForObject, if SafeVariantChangeType fails, would the data (potentially BSTR or something else) in vtmp be leaked? SafeVariantClear won't be called in throwing path.

I've concluded that SafeVariantChangeType is unnecessary and will always fail. The content of the VARIANT should be cleared at managed side in failing path.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

@AaronRobinsonMSFT Can you answer remaining questions in this PR?

The concern is about cleanup in exceptional cases with partial result. When taking a ref at managed side, RAII at native side may take care of the cleanup.
I still want to keep the current implementation and shape as possible.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

Is there anything remaining in this? I think we should aim to merge this to avoid more conflicts with other refactoring.

@AaronRobinsonMSFT

Copy link
Copy Markdown
Member

Thanks @huoyaoyuan. Appreciate the work here. I would ask that you please avoid converting more of the legacy COM interop code. The interop team is slowing making out way through it and it is both a learning exercise for us to understand what we support and how best to integrate it into the current code base.

It is doubly costly for us when there is inevtiably a missed compat case and we need to track it down. It is best left for the interop team to port over. I appreciate the added tests, but many of the questions you've asked are only answerable as we slowly detangle/understand the existing code.

Again, we do appreciate this PR, but we would prefer porting more commonly used code paths that have less impact to legacy and fragile .NET code bases.

@AaronRobinsonMSFT Can you answer remaining questions in this PR?

The best way to address these issue is through additional testing. These code paths are very old and subtle in many ways. I will try and do one more pass soon so we can get this specific PR in.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

No problem. I was assuming that you have enough knowledge to answer all the questions raised. But apparently you may need to spend similar effort than me to understand the scenarios, or even more effort to be responsible for every corner cases.

My interest in this was originally raised up when learning the types evolved with interop. Currently I have no extra work beyond this.

@AaronRobinsonMSFTAaronRobinsonMSFT left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@AaronRobinsonMSFT
AaronRobinsonMSFT merged commit c1a9f26 into dotnet:mainAug 28, 2024
@huoyaoyuan
huoyaoyuan deleted the variant-2 branch August 28, 2024 02:43
jtschuster pushed a commit to jtschuster/runtime that referenced this pull request Sep 17, 2024
* Handle simple cases of MarshalComVariantForOleVariant
* Pseudo code for MarshalOleVariantForComVariant
* Complete and setup managed call for MarshalObjectForOleVariant
* Setup MarshalHelperConvertObjectToVariant except record
* Setup MarshalHelperCastVariant
* Cleanup Variant struct and FCall
* Handle record case
* Cleanup VariantOleToCom/VariantComToOle routines
* Remove VariantData definition at unmanaged side
* Eliminate a dead branch for ref
* Remove CVTypes in native
* Share GetComIPFromObjectRef
* Add tests for managed to native side
* Add test for native to managed side
* Add test for byref returning to BYREF
* Fix BYREF handling
* Fix array marshalling
* Fix record marshalling
* Fix VT_VARIANT case
* Cleanup and fix IUnknown case
* Add more test for VT_UNKNOWN
* Cleanup for VT_VARIANT
* Cleanup SR and comment
* Fix contract in GetTypeHandleForVarType
* Move VariantChangeTypeEx to coreclr
* Add unmanaged fast path for (U)Int64
* Make ComVariant immutable
* Add GCPROTECT in ConvertSystemColorToOleColor
* Fix variant init
* Fix BYREF|EMPTY
* Initialize ComVariant
* Move GCPROTECT to the QCall
* Pass UnknownWrapper through SetFieldsObject
* Apply suggestions from code review
Co-authored-by: Aaron Robinson <arobins@microsoft.com>
* Suggestions at native side
* Rename ComIP
* Add comments for ConvertWrappedObject
* Try convert to RECORD for all cases
* Dispose Variant on failure
* Update formatting
* Fix NO_MAPPING definition
---------
Co-authored-by: Aaron Robinson <arobins@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Sep 28, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-Interop-coreclrcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@huoyaoyuan@AaronRobinsonMSFT@jkoritzinsky
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Cleanup VARIANT marshalling and convert to managed - #102498

Merged
AaronRobinsonMSFT merged 48 commits into
dotnet:mainfrom
huoyaoyuan:variant-2
Aug 28, 2024
Merged

Cleanup VARIANT marshalling and convert to managed#102498
AaronRobinsonMSFT merged 48 commits into
dotnet:mainfrom
huoyaoyuan:variant-2

Conversation

@huoyaoyuan

Copy link
Copy Markdown
Member

Cleans up the managed Variant struct used as an intermediate value.

Basically, folds MarshalHelperConvertObjectToVariant with MarshalOleVariantForComVariant, MarshalHelperConvertVariantToObject and MarshalHelperCastVariant with MarshalComVariantForOleVariant.

Tests were first written and tested on main.

Array and record marshalling are still kept native. VT_ARRAY marshalling looks sharing many logic with non-variant marshalling.

@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label May 21, 2024
Comment threadsrc/coreclr/System.Private.CoreLib/src/System/Variant.cs
Comment threadsrc/coreclr/vm/olevariant.cpp Outdated
Comment threadsrc/coreclr/vm/olevariant.cpp Outdated
Comment on lines +352 to 356
case VarEnum.VT_RECORD:
MarshalHelperConvertObjectToVariant(pValue, out v);
if (v.VarType != VarEnum.VT_RECORD)
throw new InvalidCastException(SR.InvalidCast_CannotCoerceByRefVariant);
break;

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to restore the behavior here, and relying on the location to be cleaned up by RAII at native side.
Is there any better option for this?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the previous behavior in this case? I'm not following the issue being hit here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any destructors in MarshalOleRefVariantForObject. Is that where you are talking about?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously in MarshalOleRefVariantForObject, if SafeVariantChangeType fails, would the data (potentially BSTR or something else) in vtmp be leaked? SafeVariantClear won't be called in throwing path.

I've concluded that SafeVariantChangeType is unnecessary and will always fail. The content of the VARIANT should be cleared at managed side in failing path.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

@AaronRobinsonMSFT Can you answer remaining questions in this PR?

The concern is about cleanup in exceptional cases with partial result. When taking a ref at managed side, RAII at native side may take care of the cleanup.
I still want to keep the current implementation and shape as possible.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

Is there anything remaining in this? I think we should aim to merge this to avoid more conflicts with other refactoring.

@AaronRobinsonMSFT

Copy link
Copy Markdown
Member

Thanks @huoyaoyuan. Appreciate the work here. I would ask that you please avoid converting more of the legacy COM interop code. The interop team is slowing making out way through it and it is both a learning exercise for us to understand what we support and how best to integrate it into the current code base.

It is doubly costly for us when there is inevtiably a missed compat case and we need to track it down. It is best left for the interop team to port over. I appreciate the added tests, but many of the questions you've asked are only answerable as we slowly detangle/understand the existing code.

Again, we do appreciate this PR, but we would prefer porting more commonly used code paths that have less impact to legacy and fragile .NET code bases.

@AaronRobinsonMSFT Can you answer remaining questions in this PR?

The best way to address these issue is through additional testing. These code paths are very old and subtle in many ways. I will try and do one more pass soon so we can get this specific PR in.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

No problem. I was assuming that you have enough knowledge to answer all the questions raised. But apparently you may need to spend similar effort than me to understand the scenarios, or even more effort to be responsible for every corner cases.

My interest in this was originally raised up when learning the types evolved with interop. Currently I have no extra work beyond this.

@AaronRobinsonMSFTAaronRobinsonMSFT left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@AaronRobinsonMSFT
AaronRobinsonMSFT merged commit c1a9f26 into dotnet:mainAug 28, 2024
@huoyaoyuan
huoyaoyuan deleted the variant-2 branch August 28, 2024 02:43
jtschuster pushed a commit to jtschuster/runtime that referenced this pull request Sep 17, 2024
* Handle simple cases of MarshalComVariantForOleVariant
* Pseudo code for MarshalOleVariantForComVariant
* Complete and setup managed call for MarshalObjectForOleVariant
* Setup MarshalHelperConvertObjectToVariant except record
* Setup MarshalHelperCastVariant
* Cleanup Variant struct and FCall
* Handle record case
* Cleanup VariantOleToCom/VariantComToOle routines
* Remove VariantData definition at unmanaged side
* Eliminate a dead branch for ref
* Remove CVTypes in native
* Share GetComIPFromObjectRef
* Add tests for managed to native side
* Add test for native to managed side
* Add test for byref returning to BYREF
* Fix BYREF handling
* Fix array marshalling
* Fix record marshalling
* Fix VT_VARIANT case
* Cleanup and fix IUnknown case
* Add more test for VT_UNKNOWN
* Cleanup for VT_VARIANT
* Cleanup SR and comment
* Fix contract in GetTypeHandleForVarType
* Move VariantChangeTypeEx to coreclr
* Add unmanaged fast path for (U)Int64
* Make ComVariant immutable
* Add GCPROTECT in ConvertSystemColorToOleColor
* Fix variant init
* Fix BYREF|EMPTY
* Initialize ComVariant
* Move GCPROTECT to the QCall
* Pass UnknownWrapper through SetFieldsObject
* Apply suggestions from code review
Co-authored-by: Aaron Robinson <arobins@microsoft.com>
* Suggestions at native side
* Rename ComIP
* Add comments for ConvertWrappedObject
* Try convert to RECORD for all cases
* Dispose Variant on failure
* Update formatting
* Fix NO_MAPPING definition
---------
Co-authored-by: Aaron Robinson <arobins@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Sep 28, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-Interop-coreclrcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@huoyaoyuan@AaronRobinsonMSFT@jkoritzinsky
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Cleanup VARIANT marshalling and convert to managed - #102498

Merged
AaronRobinsonMSFT merged 48 commits into
dotnet:mainfrom
huoyaoyuan:variant-2
Aug 28, 2024
Merged

Cleanup VARIANT marshalling and convert to managed#102498
AaronRobinsonMSFT merged 48 commits into
dotnet:mainfrom
huoyaoyuan:variant-2

Conversation

@huoyaoyuan

Copy link
Copy Markdown
Member

Cleans up the managed Variant struct used as an intermediate value.

Basically, folds MarshalHelperConvertObjectToVariant with MarshalOleVariantForComVariant, MarshalHelperConvertVariantToObject and MarshalHelperCastVariant with MarshalComVariantForOleVariant.

Tests were first written and tested on main.

Array and record marshalling are still kept native. VT_ARRAY marshalling looks sharing many logic with non-variant marshalling.

@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label May 21, 2024
Comment threadsrc/coreclr/System.Private.CoreLib/src/System/Variant.cs
Comment threadsrc/coreclr/vm/olevariant.cpp Outdated
Comment threadsrc/coreclr/vm/olevariant.cpp Outdated
Comment on lines +352 to 356
case VarEnum.VT_RECORD:
MarshalHelperConvertObjectToVariant(pValue, out v);
if (v.VarType != VarEnum.VT_RECORD)
throw new InvalidCastException(SR.InvalidCast_CannotCoerceByRefVariant);
break;

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to restore the behavior here, and relying on the location to be cleaned up by RAII at native side.
Is there any better option for this?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the previous behavior in this case? I'm not following the issue being hit here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any destructors in MarshalOleRefVariantForObject. Is that where you are talking about?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously in MarshalOleRefVariantForObject, if SafeVariantChangeType fails, would the data (potentially BSTR or something else) in vtmp be leaked? SafeVariantClear won't be called in throwing path.

I've concluded that SafeVariantChangeType is unnecessary and will always fail. The content of the VARIANT should be cleared at managed side in failing path.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

@AaronRobinsonMSFT Can you answer remaining questions in this PR?

The concern is about cleanup in exceptional cases with partial result. When taking a ref at managed side, RAII at native side may take care of the cleanup.
I still want to keep the current implementation and shape as possible.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

Is there anything remaining in this? I think we should aim to merge this to avoid more conflicts with other refactoring.

@AaronRobinsonMSFT

Copy link
Copy Markdown
Member

Thanks @huoyaoyuan. Appreciate the work here. I would ask that you please avoid converting more of the legacy COM interop code. The interop team is slowing making out way through it and it is both a learning exercise for us to understand what we support and how best to integrate it into the current code base.

It is doubly costly for us when there is inevtiably a missed compat case and we need to track it down. It is best left for the interop team to port over. I appreciate the added tests, but many of the questions you've asked are only answerable as we slowly detangle/understand the existing code.

Again, we do appreciate this PR, but we would prefer porting more commonly used code paths that have less impact to legacy and fragile .NET code bases.

@AaronRobinsonMSFT Can you answer remaining questions in this PR?

The best way to address these issue is through additional testing. These code paths are very old and subtle in many ways. I will try and do one more pass soon so we can get this specific PR in.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

No problem. I was assuming that you have enough knowledge to answer all the questions raised. But apparently you may need to spend similar effort than me to understand the scenarios, or even more effort to be responsible for every corner cases.

My interest in this was originally raised up when learning the types evolved with interop. Currently I have no extra work beyond this.

@AaronRobinsonMSFTAaronRobinsonMSFT left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@AaronRobinsonMSFT
AaronRobinsonMSFT merged commit c1a9f26 into dotnet:mainAug 28, 2024
@huoyaoyuan
huoyaoyuan deleted the variant-2 branch August 28, 2024 02:43
jtschuster pushed a commit to jtschuster/runtime that referenced this pull request Sep 17, 2024
* Handle simple cases of MarshalComVariantForOleVariant
* Pseudo code for MarshalOleVariantForComVariant
* Complete and setup managed call for MarshalObjectForOleVariant
* Setup MarshalHelperConvertObjectToVariant except record
* Setup MarshalHelperCastVariant
* Cleanup Variant struct and FCall
* Handle record case
* Cleanup VariantOleToCom/VariantComToOle routines
* Remove VariantData definition at unmanaged side
* Eliminate a dead branch for ref
* Remove CVTypes in native
* Share GetComIPFromObjectRef
* Add tests for managed to native side
* Add test for native to managed side
* Add test for byref returning to BYREF
* Fix BYREF handling
* Fix array marshalling
* Fix record marshalling
* Fix VT_VARIANT case
* Cleanup and fix IUnknown case
* Add more test for VT_UNKNOWN
* Cleanup for VT_VARIANT
* Cleanup SR and comment
* Fix contract in GetTypeHandleForVarType
* Move VariantChangeTypeEx to coreclr
* Add unmanaged fast path for (U)Int64
* Make ComVariant immutable
* Add GCPROTECT in ConvertSystemColorToOleColor
* Fix variant init
* Fix BYREF|EMPTY
* Initialize ComVariant
* Move GCPROTECT to the QCall
* Pass UnknownWrapper through SetFieldsObject
* Apply suggestions from code review
Co-authored-by: Aaron Robinson <arobins@microsoft.com>
* Suggestions at native side
* Rename ComIP
* Add comments for ConvertWrappedObject
* Try convert to RECORD for all cases
* Dispose Variant on failure
* Update formatting
* Fix NO_MAPPING definition
---------
Co-authored-by: Aaron Robinson <arobins@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Sep 28, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-Interop-coreclrcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@huoyaoyuan@AaronRobinsonMSFT@jkoritzinsky
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Cleanup VARIANT marshalling and convert to managed - #102498

Merged
AaronRobinsonMSFT merged 48 commits into
dotnet:mainfrom
huoyaoyuan:variant-2
Aug 28, 2024
Merged

Cleanup VARIANT marshalling and convert to managed#102498
AaronRobinsonMSFT merged 48 commits into
dotnet:mainfrom
huoyaoyuan:variant-2

Conversation

@huoyaoyuan

Copy link
Copy Markdown
Member

Cleans up the managed Variant struct used as an intermediate value.

Basically, folds MarshalHelperConvertObjectToVariant with MarshalOleVariantForComVariant, MarshalHelperConvertVariantToObject and MarshalHelperCastVariant with MarshalComVariantForOleVariant.

Tests were first written and tested on main.

Array and record marshalling are still kept native. VT_ARRAY marshalling looks sharing many logic with non-variant marshalling.

@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label May 21, 2024
Comment threadsrc/coreclr/System.Private.CoreLib/src/System/Variant.cs
Comment threadsrc/coreclr/vm/olevariant.cpp Outdated
Comment threadsrc/coreclr/vm/olevariant.cpp Outdated
Comment on lines +352 to 356
case VarEnum.VT_RECORD:
MarshalHelperConvertObjectToVariant(pValue, out v);
if (v.VarType != VarEnum.VT_RECORD)
throw new InvalidCastException(SR.InvalidCast_CannotCoerceByRefVariant);
break;

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to restore the behavior here, and relying on the location to be cleaned up by RAII at native side.
Is there any better option for this?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the previous behavior in this case? I'm not following the issue being hit here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any destructors in MarshalOleRefVariantForObject. Is that where you are talking about?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously in MarshalOleRefVariantForObject, if SafeVariantChangeType fails, would the data (potentially BSTR or something else) in vtmp be leaked? SafeVariantClear won't be called in throwing path.

I've concluded that SafeVariantChangeType is unnecessary and will always fail. The content of the VARIANT should be cleared at managed side in failing path.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

@AaronRobinsonMSFT Can you answer remaining questions in this PR?

The concern is about cleanup in exceptional cases with partial result. When taking a ref at managed side, RAII at native side may take care of the cleanup.
I still want to keep the current implementation and shape as possible.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

Is there anything remaining in this? I think we should aim to merge this to avoid more conflicts with other refactoring.

@AaronRobinsonMSFT

Copy link
Copy Markdown
Member

Thanks @huoyaoyuan. Appreciate the work here. I would ask that you please avoid converting more of the legacy COM interop code. The interop team is slowing making out way through it and it is both a learning exercise for us to understand what we support and how best to integrate it into the current code base.

It is doubly costly for us when there is inevtiably a missed compat case and we need to track it down. It is best left for the interop team to port over. I appreciate the added tests, but many of the questions you've asked are only answerable as we slowly detangle/understand the existing code.

Again, we do appreciate this PR, but we would prefer porting more commonly used code paths that have less impact to legacy and fragile .NET code bases.

@AaronRobinsonMSFT Can you answer remaining questions in this PR?

The best way to address these issue is through additional testing. These code paths are very old and subtle in many ways. I will try and do one more pass soon so we can get this specific PR in.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

No problem. I was assuming that you have enough knowledge to answer all the questions raised. But apparently you may need to spend similar effort than me to understand the scenarios, or even more effort to be responsible for every corner cases.

My interest in this was originally raised up when learning the types evolved with interop. Currently I have no extra work beyond this.

@AaronRobinsonMSFTAaronRobinsonMSFT left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@AaronRobinsonMSFT
AaronRobinsonMSFT merged commit c1a9f26 into dotnet:mainAug 28, 2024
@huoyaoyuan
huoyaoyuan deleted the variant-2 branch August 28, 2024 02:43
jtschuster pushed a commit to jtschuster/runtime that referenced this pull request Sep 17, 2024
* Handle simple cases of MarshalComVariantForOleVariant
* Pseudo code for MarshalOleVariantForComVariant
* Complete and setup managed call for MarshalObjectForOleVariant
* Setup MarshalHelperConvertObjectToVariant except record
* Setup MarshalHelperCastVariant
* Cleanup Variant struct and FCall
* Handle record case
* Cleanup VariantOleToCom/VariantComToOle routines
* Remove VariantData definition at unmanaged side
* Eliminate a dead branch for ref
* Remove CVTypes in native
* Share GetComIPFromObjectRef
* Add tests for managed to native side
* Add test for native to managed side
* Add test for byref returning to BYREF
* Fix BYREF handling
* Fix array marshalling
* Fix record marshalling
* Fix VT_VARIANT case
* Cleanup and fix IUnknown case
* Add more test for VT_UNKNOWN
* Cleanup for VT_VARIANT
* Cleanup SR and comment
* Fix contract in GetTypeHandleForVarType
* Move VariantChangeTypeEx to coreclr
* Add unmanaged fast path for (U)Int64
* Make ComVariant immutable
* Add GCPROTECT in ConvertSystemColorToOleColor
* Fix variant init
* Fix BYREF|EMPTY
* Initialize ComVariant
* Move GCPROTECT to the QCall
* Pass UnknownWrapper through SetFieldsObject
* Apply suggestions from code review
Co-authored-by: Aaron Robinson <arobins@microsoft.com>
* Suggestions at native side
* Rename ComIP
* Add comments for ConvertWrappedObject
* Try convert to RECORD for all cases
* Dispose Variant on failure
* Update formatting
* Fix NO_MAPPING definition
---------
Co-authored-by: Aaron Robinson <arobins@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Sep 28, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-Interop-coreclrcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@huoyaoyuan@AaronRobinsonMSFT@jkoritzinsky
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Cleanup VARIANT marshalling and convert to managed - #102498

Merged
AaronRobinsonMSFT merged 48 commits into
dotnet:mainfrom
huoyaoyuan:variant-2
Aug 28, 2024
Merged

Cleanup VARIANT marshalling and convert to managed#102498
AaronRobinsonMSFT merged 48 commits into
dotnet:mainfrom
huoyaoyuan:variant-2

Conversation

@huoyaoyuan

Copy link
Copy Markdown
Member

Cleans up the managed Variant struct used as an intermediate value.

Basically, folds MarshalHelperConvertObjectToVariant with MarshalOleVariantForComVariant, MarshalHelperConvertVariantToObject and MarshalHelperCastVariant with MarshalComVariantForOleVariant.

Tests were first written and tested on main.

Array and record marshalling are still kept native. VT_ARRAY marshalling looks sharing many logic with non-variant marshalling.

@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label May 21, 2024
Comment threadsrc/coreclr/System.Private.CoreLib/src/System/Variant.cs
Comment threadsrc/coreclr/vm/olevariant.cpp Outdated
Comment threadsrc/coreclr/vm/olevariant.cpp Outdated
Comment on lines +352 to 356
case VarEnum.VT_RECORD:
MarshalHelperConvertObjectToVariant(pValue, out v);
if (v.VarType != VarEnum.VT_RECORD)
throw new InvalidCastException(SR.InvalidCast_CannotCoerceByRefVariant);
break;

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to restore the behavior here, and relying on the location to be cleaned up by RAII at native side.
Is there any better option for this?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the previous behavior in this case? I'm not following the issue being hit here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any destructors in MarshalOleRefVariantForObject. Is that where you are talking about?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously in MarshalOleRefVariantForObject, if SafeVariantChangeType fails, would the data (potentially BSTR or something else) in vtmp be leaked? SafeVariantClear won't be called in throwing path.

I've concluded that SafeVariantChangeType is unnecessary and will always fail. The content of the VARIANT should be cleared at managed side in failing path.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

@AaronRobinsonMSFT Can you answer remaining questions in this PR?

The concern is about cleanup in exceptional cases with partial result. When taking a ref at managed side, RAII at native side may take care of the cleanup.
I still want to keep the current implementation and shape as possible.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

Is there anything remaining in this? I think we should aim to merge this to avoid more conflicts with other refactoring.

@AaronRobinsonMSFT

Copy link
Copy Markdown
Member

Thanks @huoyaoyuan. Appreciate the work here. I would ask that you please avoid converting more of the legacy COM interop code. The interop team is slowing making out way through it and it is both a learning exercise for us to understand what we support and how best to integrate it into the current code base.

It is doubly costly for us when there is inevtiably a missed compat case and we need to track it down. It is best left for the interop team to port over. I appreciate the added tests, but many of the questions you've asked are only answerable as we slowly detangle/understand the existing code.

Again, we do appreciate this PR, but we would prefer porting more commonly used code paths that have less impact to legacy and fragile .NET code bases.

@AaronRobinsonMSFT Can you answer remaining questions in this PR?

The best way to address these issue is through additional testing. These code paths are very old and subtle in many ways. I will try and do one more pass soon so we can get this specific PR in.

@huoyaoyuan

Copy link
Copy Markdown
MemberAuthor

No problem. I was assuming that you have enough knowledge to answer all the questions raised. But apparently you may need to spend similar effort than me to understand the scenarios, or even more effort to be responsible for every corner cases.

My interest in this was originally raised up when learning the types evolved with interop. Currently I have no extra work beyond this.

@AaronRobinsonMSFTAaronRobinsonMSFT left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@AaronRobinsonMSFT
AaronRobinsonMSFT merged commit c1a9f26 into dotnet:mainAug 28, 2024
@huoyaoyuan
huoyaoyuan deleted the variant-2 branch August 28, 2024 02:43
jtschuster pushed a commit to jtschuster/runtime that referenced this pull request Sep 17, 2024
* Handle simple cases of MarshalComVariantForOleVariant
* Pseudo code for MarshalOleVariantForComVariant
* Complete and setup managed call for MarshalObjectForOleVariant
* Setup MarshalHelperConvertObjectToVariant except record
* Setup MarshalHelperCastVariant
* Cleanup Variant struct and FCall
* Handle record case
* Cleanup VariantOleToCom/VariantComToOle routines
* Remove VariantData definition at unmanaged side
* Eliminate a dead branch for ref
* Remove CVTypes in native
* Share GetComIPFromObjectRef
* Add tests for managed to native side
* Add test for native to managed side
* Add test for byref returning to BYREF
* Fix BYREF handling
* Fix array marshalling
* Fix record marshalling
* Fix VT_VARIANT case
* Cleanup and fix IUnknown case
* Add more test for VT_UNKNOWN
* Cleanup for VT_VARIANT
* Cleanup SR and comment
* Fix contract in GetTypeHandleForVarType
* Move VariantChangeTypeEx to coreclr
* Add unmanaged fast path for (U)Int64
* Make ComVariant immutable
* Add GCPROTECT in ConvertSystemColorToOleColor
* Fix variant init
* Fix BYREF|EMPTY
* Initialize ComVariant
* Move GCPROTECT to the QCall
* Pass UnknownWrapper through SetFieldsObject
* Apply suggestions from code review
Co-authored-by: Aaron Robinson <arobins@microsoft.com>
* Suggestions at native side
* Rename ComIP
* Add comments for ConvertWrappedObject
* Try convert to RECORD for all cases
* Dispose Variant on failure
* Update formatting
* Fix NO_MAPPING definition
---------
Co-authored-by: Aaron Robinson <arobins@microsoft.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Sep 28, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-Interop-coreclrcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@huoyaoyuan@AaronRobinsonMSFT@jkoritzinsky