Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 159103
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 11, 20262026-05-11T10:47:58+00:00 2026-05-11T10:47:58+00:00

I am working on a system that requires interaction with a native C API

  • 0

I am working on a system that requires interaction with a native C API using P/Invoke. Now I’ve (yet again) stumbled upon a problem which I cannot seem to solve in any way. The original function is designed to return 2 kinds of structures, based on a parameter that specifies which structure to use.

The C header file defines the structures and function as follows:

#pragma pack(1) typedef struct {    DWORD JobId;     DWORD CardNum;    HANDLE hPrinter; } CARDIDTYPE, FAR *LPCARDIDTYPE; #pragma pack()  typedef struct {    BOOL        bActive;    BOOL        bSuccess; } CARD_INFO_1, *PCARD_INFO_1, FAR *LPCARD_INFO_1;  typedef struct {    DWORD       dwCopiesPrinted;    DWORD       dwRemakeAttempts;    SYSTEMTIME  TimeCompleted; } CARD_INFO_2, *PCARD_INFO_2, FAR *LPCARD_INFO_2;  BOOL ICEAPI GetCardId(HDC hdc, LPCARDIDTYPE pCardId); BOOL ICEAPI GetCardStatus(CARDIDTYPE CardId, DWORD level, LPBYTE pData, DWORD cbBuf, LPDWORD pcbNeeded ); 

I have attempted to implement P/Invoke wrappers like this:

[StructLayout(LayoutKind.Sequential, Pack=1)] public class CARDIDTYPE {     public UInt32 JobId;     public UInt32 CardNum;     public IntPtr hPrinter; }  [StructLayout(LayoutKind.Sequential)] public class CARD_INFO_1 {     public bool bActive;     public bool bSuccess; }  [StructLayout(LayoutKind.Sequential)] public class CARD_INFO_2 {     public UInt32 dwCopiesPrinted;     public UInt32 dwRemakeAttempts;     public Win32Util.SYSTEMTIME TimeCompleted; } [DllImport('ICE_API.DLL', CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi, SetLastError = true)] public static extern bool GetCardId(HandleRef hDC, [Out]CARDIDTYPE pCardId);  [DllImport('ICE_API.DLL', CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi, SetLastError = true)] public static extern bool GetCardStatus(CARDIDTYPE CardId, UInt32 level, [Out] byte[] pData, UInt32 cbBuf, out UInt32 pcbNeeded); 

Calling the ‘GetCardId’ seems to work fine. I get plausible data in CARDIDTYPE instance after calling it. However when I call ‘GetCardStatus’ the problems start. The type of structure that should be returned is defined by the ‘level’ param, and a value of 1 should result in a CARD_INFO_1 structure to be returnes in ‘pData’.

The documentation contains the following C example:

CARD_INFO_1 ci1; DWORD cbNeeded; ci1.bActive = TRUE; if (GetCardStatus(*lpCardID, 1, (LPBYTE)&ci1, sizeof(ci1), &cbNeeded )) { /* success */ } 

My equivalent C# implementation is like this:

uint needed; byte[] byteArray = new byte[Marshal.SizeOf(typeof(CARD_INFO_1))]; if (GetCardStatus(cardId, 1, byteArray, (uint)byteArray.Length, out needed)) { /* success */ } 

When I execute this C# code, the method returns false and Marshal.GetLastWin32Error() return -1073741737 (which does not make much sense to me). I see no reason why this call should fail, and definitely not with this error code. So I suspect I have got something wrong in my P/Invoke wrapper.

I know that using ‘byte[]’ as the type of pData is probably not correct, but according to some googling a ‘LPBYTE’ translates to ‘[Out] byte[]’. I guess the correct way to do this is to have pData as an IntPtr, and create the structure using Marshal.PtrToStructure(…). I have tried this, but the result is the same. Here is the code for this scenario:

[DllImport(@'ICE_API.DLL', CharSet = CharSet.Auto, EntryPoint = '_GetCardStatus@28', CallingConvention = CallingConvention.Winapi, SetLastError = true)] public static extern bool GetCardStatus(CARDIDTYPE CardId, UInt32 level, IntPtr pData, UInt32 cbBuf, out UInt32 pcbNeeded);  uint needed; int memSize = Marshal.SizeOf(typeof(CARD_INFO_1)); IntPtr memPtr = Marshal.AllocHGlobal(memSize); if (!GetCardStatus(cardId, 1, memPtr, (uint)memSize, out needed)) {     int lastError = Marshal.GetLastWin32Error();     // error code is -1073741737 } CARD_INFO_1 info = (CARD_INFO_1)Marshal.PtrToStructure(memPtr, typeof(CARD_INFO_1)); Marshal.FreeHGlobal(memPtr); 

Edit: One thing I forgot to mention is that for some reason the GetCardStatus call fails with an unknown entry point exception if I do not specify EntryPoint = ‘_GetCardStatus@28’. This has not happened to any other function I have wrapped, so it got me wondering a bit.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. 2026-05-11T10:47:59+00:00Added an answer on May 11, 2026 at 10:47 am

    _GetCardStatus@28 gave me an idea. Unless you are running on 64-bit Windows, you’ve got the number of arguments wrong. Your P/Invoke for GetCardStatus would be _GetCardStatus@20, because it has 5 32-bit arguments. Your C declaration of GetCardStatus seems to accept the cardId by value rather than by reference. Since CARDIDTYPE is 12 bytes long, this would give the correct length of the argument list (28). Moreover, this would explain both your receiving an error code of -1073741737 (C0000057, STATUS_INVALID_PARAMETER) — since you’re not passing a valid cardId — and the access violation — GetCardStatus tries to write to pcbNeeded, which is garbage because the marshaler hasn’t even pushed it!

    Ergo:

    [DllImport('ICE_API.DLL', CharSet = CharSet.Auto,       CallingConvention = CallingConvention.Winapi, SetLastError = true)]  public static extern bool GetCardStatus (      IntPtr hPrinter, UInt32 cardNum, UInt32 jobId, UInt32 level,      [In, Out] CARD_INFO_1 data, UInt32 cbBuf, out UInt32 pcbNeeded) ; [DllImport('ICE_API.DLL', CharSet = CharSet.Auto,       CallingConvention = CallingConvention.Winapi, SetLastError = true)]  public static extern bool GetCardStatus (      IntPtr hPrinter, UInt32 cardNum, UInt32 jobId, UInt32 level,      [In, Out] CARD_INFO_2 data, UInt32 cbBuf, out UInt32 pcbNeeded) ; 

    Note reverse order of the three CARDIDTYPE members: stdcall pushes the parameters left-to-right (i.e. towards lower addresses), and my guess is that a struct is ‘pushed’ as a unit.

    Also, if you later close the printer handle with CloseHandle, I’d suggest receiving the handle in CARDIDTYPE into an appropriate SafeHandle, not into a bare IntPtr, and declaring GetCardStatus to receive the safe handle.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Ask A Question

Stats

  • Questions 89k
  • Answers 89k
  • Best Answers 0
  • User 1
  • Popular
  • Answers
  • Editorial Team

    How to approach applying for a job at a company ...

    • 7 Answers
  • Editorial Team

    How to handle personal stress caused by utterly incompetent and ...

    • 5 Answers
  • Editorial Team

    What is a programmer’s life like?

    • 5 Answers
  • Editorial Team
    Editorial Team added an answer I doubt there's a nice compiled list out there yet… May 11, 2026 at 5:52 pm
  • Editorial Team
    Editorial Team added an answer Because of the lack of information out there on this,… May 11, 2026 at 5:52 pm
  • Editorial Team
    Editorial Team added an answer The PIC architecture is as atomic as it gets. It… May 11, 2026 at 5:52 pm

Related Questions

The project I am working on were are trying to come up with a
I am working on a project that requires the manipulation of enormous matrices, specifically
I'm working on a web app that is somewhere between an email service and
I am designing a system which will at some point require to send email

Trending Tags

analytics british company computer developers django employee employer english facebook french google interview javascript language life php programmer programs salary

Top Members

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.