0

I have implemented and used the code snippet from the post:

Add proper p/invoke signature to PowerShell script

However, the script only works consistently if run from PowerShell ISE or if embedded as a function in a module and then call it implicitly (Module Auto-Loading).

Otherwise, I receive the following error message right before the console crashes:

Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

at System.Runtime.InteropServices.Marshal.PtrToStructureHelper(IntPtr ptr, Object structure, Boolean allowValueClasses)

at System.Runtime.InteropServices.Marshal.PtrToStructure(IntPtr ptr, Type structureType) ...

Can anyone point me in the right direction to solve this issue / bug?

Kanuc
  • 25
  • 6
  • Are you using Cryptnet.dll? Error is a typical error message when calling a dll from a c# application. A pointer is invalid causing a memory exception which can be due to lots of reasons. Are you using the entire posted code or only a portion? Which portion is failing. Did you read the comments? OP was getting same error you are getting. – jdweng Nov 09 '22 at 10:56
  • String in c language are a byte array terminating with a '\0' character. So in c# you declare these object as a UnmanagedType.LPArray. The error in link was due to the SizePaarameter on using two character for the array. Looks like code was taken from `www.pinvoke.net' where code is also wrong. It was used in following https://www.pinvoke.net/default.aspx/crypt32/CertVerifyCRLRevocation.html Using SizeParamIndex=2 on a INtPtr[] is correct but not on a byte[] in the CRL_Context structure. – jdweng Nov 09 '22 at 11:07
  • @jdweng, first of all, thanks. I’ll try to answer your questions one by one. Yes, I’m using Cryptnet.dll for the function CryptRetrieveObjectByUrl and Crypt32.dll for the function CertFreeCRLContext plus the necessary structs. Regarding the other post, I was the one posting it so, yes, I’m using all the code in the snippet. Moreover, following the comments made by **mclayton** allowed me to get a well-formed object. – Kanuc Nov 09 '22 at 13:44
  • Sorry I didn't notice you were the OP. The date was from July. Powershell is ignoring the exception while c# which is managed is reporting the exception. I would go back to the pinvoke struct and use what is in Pinvoke. Did you try getting last error? I think error may be CharSet = CharSet.Auto. Try instead CharSet.Ansi. You are getting two strings for start and end times. See https://learn.microsoft.com/en-us/dotnet/framework/interop/default-marshalling-for-strings – jdweng Nov 09 '22 at 14:44
  • Code is intermittent so may be a pack issue. See : May be a pack issue : https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.structlayoutattribute.pack?view=net-6.0&force_isolation=true The compiler mode (16,32,64) may not be the same as dll. So try pack 64 and see what happens. – jdweng Nov 09 '22 at 14:45
  • @jdweng , The method Marshal.GetLastWin32Error() returns 0 because the function CryptRetrieveObjectByUrl is successful (True) and the out parameter ppvObject has a pointer as expected. I’ve followed your advise and use CharSet=CharSet.Ansi throughout the declaration of functions and structs, as well as explicitly using [MarshalAs(UnmanagedType.LPStr)] for string arguments in functions and attributes in structs; I’ve also make sure that the input strings have a null-terminating character: so far I’ve not seen any changes. The same goes for using the Pack attribute when declaring the structs. – Kanuc Nov 09 '22 at 16:56
  • If it is an array of IntPtr[] rgpCrlInfo than you need a '\0 at end of array. A Intpr is 4 bytes so it doesn't matter if your declare as uint or Intptr. c# is managed code and sets up a Selector on the Micro for the expected start and end address. If you program access memory outside the Selector you will get an exception. So if the compiler option and code do not agree you can get a few bytes of memory that falls outside the Selector and get an exception. Normally this happens when the dll is called, and not in the middle of running dll. So how fast the error occurs is sometimes a clue. – jdweng Nov 09 '22 at 17:13
  • Make sure the return size of the dll matches the return size in c#. I've seen errors when they do not match. – jdweng Nov 09 '22 at 18:31

0 Answers0