Ejemplo n.º 1
0
        public static byte[] GetCard()
        {
            ServioCardInfo res = new ServioCardInfo {
                ErrorCore = -1, CardNumber = "", IssuerID = -1
            };
            IntPtr obj = new IntPtr();

            if ((res.ErrorCore = InitInternal(_config, ref obj)) != 0)
            {
                throw new CardShellException("Error Init No" + res, res.ErrorCore);
            }

            IntPtr serialNumberPtr = Marshal.AllocHGlobal(sizeof(SerialnumberT));
            IntPtr cardImagePtr    = Marshal.AllocHGlobal(sizeof(Mf1S70T));

            UnMemory <byte> .SaveInMemArr(new byte[Mf1S70T.Size], ref cardImagePtr);

            if ((res.ErrorCore = ReadCard(obj, serialNumberPtr, cardImagePtr, false)) != 0)
            {
                throw new CardShellException("Error ReadCard No" + res, res.ErrorCore);
            }

            var blocks = UnMemory <Mf1S70T> .ReadInMem(cardImagePtr);

            var card = blocks.GetBlocks();

            return(card);
        }
Ejemplo n.º 2
0
        public static int LoadKey(IntPtr obj, int sector, int keyTypeInt, bool nonvolatileMemory, int keyIndex, IntPtr key)
        {
            string text =
                $"!!! LoadKey !!!\tobj:{obj}\tSector:{sector}\tKeyType:{keyTypeInt}\tNonvolatileMemory:{nonvolatileMemory}\tKeyIndex:{keyIndex}\tKey:{key}\t";

            WriteToLog(text);
            try
            {
                if (_keys != null && _card != null)
                {
                    byte[] keyR = UnMemory <byte> .ReadInMemArr(key, 6);

                    _keys[new Tuple <int, int>(sector, keyTypeInt)] = new Tuple <int, bool, byte[]>(keyIndex, nonvolatileMemory, keyR);

                    text =
                        $"!!! LoadKey over !!!\tSector:{sector}\tKeyType:{keyTypeInt}\tKeyIndex:{keyIndex}\tkey:{BitConverter.ToString(keyR ?? new byte[] {})}\t";
                    //WriteToLog(text);
                }
                return((int)ErrorCodes.E_SUCCESS);
            }
            catch (Exception e)
            {
                WriteToLog($"LoadKey ERROR !!! {text}\r\n {e}");
                return((int)ErrorCodes.E_POS_KEYS_LOAD);
            }
        }
Ejemplo n.º 3
0
        public static int WriteBlock(IntPtr obj, int block, IntPtr data)
        {
            string text =
                $"!!! WriteBlock !!!\tobj:{obj}\tBlock:{block}\tData:{data}\t";

            WriteToLog(text);
            try
            {
                if (_card != null)
                {
                    int blockInSector;
                    int controlSector;
                    BlockToSectorBlock(block, out controlSector, out blockInSector);

                    byte[] dat = UnMemory <byte> .ReadInMemArr(data, 16);

                    var keyA = GetKeyFromCollection(controlSector, 0);
                    var keyB = GetKeyFromCollection(controlSector, 1);

                    text =
                        $"!!! WriteBlock internal !!!\tcurrentSector: {controlSector}\tblockInSector: {blockInSector}\tkeyA: {BitConverter.ToString(keyA ?? new byte[] { })}\tkeyB: {BitConverter.ToString(keyB ?? new byte[] { })}\tData:{BitConverter.ToString(dat ?? new byte[] { })}\t";
                    //WriteToLog(text);

                    //TODO убрать
                    //if (_cardBadSectors?.Contains(new Tuple<int, int>(controlSector, blockInSector)) ?? false)
                    //{
                    //    WriteOrReplaceToFileSector(controlSector, blockInSector, dat);
                    //    text = "!!! WriteBlock to file!";
                    //    //WriteToLog(text);
                    //    return (int)ErrorCodes.E_SUCCESS;
                    //}

                    //WriteDataToLog(controlSector, blockInSector, data.ByteArrayToString(), true);

                    var result = SetData(dat, controlSector, blockInSector, keyA, keyB).Result;
                    if (result == (int)ErrorCodes.E_SUCCESS)
                    {
                        result = Transfer(obj, block);
                    }

                    return(result);
                }
                WriteToLog($"WriteBlock ERROR !!! reader:{_reader} card: {_card}\r\n");
                return((int)ErrorCodes.E_CARDREADER_NOT_INIT);
            }
            catch (Exception e)
            {
                WriteToLog($"WriteBlock ERROR !!! {text}\r\n {e}");
                return((int)ErrorCodes.E_GENERIC);
            }
        }
Ejemplo n.º 4
0
        static void Main(string[] args)
        {
            Pair <char> a = new Pair <char>('A');
            Pair <char> b = new Pair <char>('B');
            Pair <char> c = new Pair <char>('C');

            Pair <int> i1 = new Pair <int>(12);
            Pair <int> i2 = new Pair <int>(567);
            Pair <int> i3 = new Pair <int>(972);

            Pair <bool> x = new Pair <bool>(true);
            Pair <bool> y = new Pair <bool>(false);

            UnMemory <char> .SaveInMemory(a.value, ref a.ptr);

            UnMemory <char> .SaveInMemory(b.value, ref b.ptr);

            UnMemory <char> .SaveInMemory(c.value, ref c.ptr);

            UnMemory <int> .SaveInMemory(i1.value, ref i1.ptr);

            UnMemory <int> .SaveInMemory(i2.value, ref i2.ptr);

            UnMemory <int> .SaveInMemory(i3.value, ref i3.ptr);

            UnMemory <bool> .SaveInMemory(x.value, ref x.ptr);

            UnMemory <bool> .SaveInMemory(y.value, ref y.ptr);

            Console.WriteLine(UnMemory <char> .ReadInMemory(a.ptr));
            Console.WriteLine(UnMemory <char> .ReadInMemory(b.ptr));
            Console.WriteLine(UnMemory <char> .ReadInMemory(c.ptr));

            Console.WriteLine(UnMemory <int> .ReadInMemory(i1.ptr));
            Console.WriteLine(UnMemory <int> .ReadInMemory(i2.ptr));
            Console.WriteLine(UnMemory <int> .ReadInMemory(i3.ptr));

            Console.WriteLine(UnMemory <bool> .ReadInMemory(x.ptr));
            Console.WriteLine(UnMemory <bool> .ReadInMemory(y.ptr));

            UnMemory.FreeMemory();
        }
Ejemplo n.º 5
0
        public static int Init([MarshalAs(UnmanagedType.LPWStr)] string /*IntPtr*/ initStr, IntPtr caps, ref IntPtr obj)
        {
            string text =
                $"!!! Init !!!\tobj:{obj}\tCaps:{caps}\tInitStr:{initStr/*Marshal.PtrToStringBSTR(initStr)*/ ?? "null"}\t";

            WriteToLog(text);
            try
            {
                UnMemory <int> .SaveInMemArr(new[] { 12, 1, 0 }, ref caps);

                var capsR = UnMemory <int> .ReadInMemArr(caps, 3);

                text =
                    $"!!! Init internal Caps !!!\tsize:{capsR[0]}\tVolatileKeySlotCount:{capsR[1]}\tNonvolatileKeySlotCount:{capsR[2]}\t";
                //WriteToLog(text);

                var res = InitializeReader().Result;

                // выделение  памяти под obj
                int pInt = 0;
                UnMemory <int> .SaveInMem(pInt, ref obj);

                _obj = obj;

                if (_keys == null)
                {
                    _keys = new Dictionary <Tuple <int, int>, Tuple <int, bool, byte[]> >();
                }
                else
                {
                    _keys.Clear();
                }

                return(res);
            }
            catch (Exception e)
            {
                WriteToLog($"Init ERROR !!! reader:{_reader} card: {_card}\r\n {e}");
                return((int)ErrorCodes.E_CARDREADER_NOT_INIT);
            }
        }
Ejemplo n.º 6
0
        public static int SelectCard(IntPtr obj, IntPtr serialNumber, int serialNumberSize)
        {
            string text =
                $"!!! SelectCard !!!\tobj:{obj}\tSerialNumber:{serialNumber}\tSerialNumberSize:{serialNumberSize}\t";

            WriteToLog(text);
            try
            {
                byte[] uid = UnMemory <byte> .ReadInMemArr(serialNumber, serialNumberSize);

                text =
                    $"!!! SelectCard over !!!\tobj:{obj}\tSerialNumber:{serialNumber}\tSerialNumberSize:{serialNumberSize}\tuid:{BitConverter.ToString(uid ?? new byte[] {})}\t";
                WriteToLog(text);
                return((int)ErrorCodes.E_SUCCESS);
            }
            catch (Exception e)
            {
                WriteToLog($"SelectCard ERROR !!! {text}\r\n {e}");
                return((int)ErrorCodes.E_GENERIC);
            }
        }
Ejemplo n.º 7
0
        public static int Anticollision(IntPtr obj, IntPtr serialNumberBuf, int bufSize, IntPtr serialNumberSize)
        {
            string text =
                $"!!! Anticollision !!!\tobj:{obj}\tSerialNumberBuf:{serialNumberBuf}\tBufSize:{bufSize}\tSerialNumberSize:{serialNumberSize}\t";

            WriteToLog(text);

            try
            {
                var uid = _card?.GetUid().Result;
                if (uid != null)
                {
                    byte[] truncUid = new byte[Math.Min(bufSize, uid.Length)];
                    Array.Copy(uid, truncUid, truncUid.Length);
                    UnMemory <int> .SaveInMem(truncUid.Length, ref serialNumberSize);

                    UnMemory <byte> .SaveInMemArr(uid, ref serialNumberBuf);

                    //Marshal.StructureToPtr(memory_object, SerialNumberBuf, true);

                    var uidWrited = UnMemory <byte> .ReadInMemArr(serialNumberBuf, truncUid.Length);

                    var serialNumberSizeWrited = UnMemory <int> .ReadInMem(serialNumberSize);

                    text =
                        $"!!! Anticollision over !!!\tobj:{obj}\tSerialNumberBuf:{serialNumberBuf}\tBufSize:{bufSize}\tuid:{BitConverter.ToString(uid)}\tuid_w:{BitConverter.ToString(uidWrited ?? new byte[] {})}\tSerialNumberSize:{serialNumberSize}\tSerialNumberSize_writed:{serialNumberSizeWrited}\t";
                    WriteToLog(text);
                    return((int)ErrorCodes.E_SUCCESS);
                }

                WriteToLog($"Anticollision ERROR !!! _card:{_card == null}\r\n uid:{uid == null}");
                return((int)ErrorCodes.E_CARDREADER_NOT_INIT);
            }
            catch (Exception e)
            {
                WriteToLog($"Anticollision ERROR !!! {text}\r\n {e}");
                return((int)ErrorCodes.E_GENERIC);
            }
        }
Ejemplo n.º 8
0
        public static int ReadBlock(IntPtr obj, int block, IntPtr buffer)
        {
            string text =
                $"!!! ReadBlock !!!\tobj:{obj}\tBlock:{block}\tBuffer:{buffer}\t";

            WriteToLog(text);
            try
            {
                if (_card != null)
                {
                    int blockInSector;
                    int controlSector;
                    BlockToSectorBlock(block, out controlSector, out blockInSector);

                    var keyA = GetKeyFromCollection(controlSector, 0);
                    var keyB = GetKeyFromCollection(controlSector, 1);

                    text =
                        $"!!! ReadBlock before !!!\tcurrentSector: {controlSector}\tblockInSector: {blockInSector}\tkeyA: {BitConverter.ToString(keyA ?? new byte[] { })}\tkeyB: {BitConverter.ToString(keyB ?? new byte[] { })}";
                    //WriteToLog(text);

                    //TODO удалить
                    if (_cardBadSectors?.Contains(new Tuple <int, int>(controlSector, blockInSector)) ?? false)
                    {
                        byte[] dataBadSectors = ReadFromFileSector(controlSector, blockInSector);

                        if (dataBadSectors.Length > 0 && dataBadSectors.Length < 17)
                        {
                            //WriteToLog($"SaveInMemory from file {dataBadSectors.Length} byte");
                            UnMemory <byte> .SaveInMemArr(dataBadSectors, ref buffer);
                        }

                        //TODO убрать логи чтения и записи
                        //WriteToLog($"Sector '{controlSector}':[{blockInSector}]{dataBadSectors.ByteArrayToString()}");
                        //WriteDataToLog(controlSector, blockInSector, dataBadSectors.ByteArrayToString(), false);
                        return((int)ErrorCodes.E_SUCCESS);
                    }

                    byte[] data = GetData(controlSector, blockInSector, keyA, keyB).Result;
                    if (data.Length > 0 && data.Length < 17)
                    {
                        //WriteToLog($"SaveInMemory {data.Length} byte");
                        UnMemory <byte> .SaveInMemArr(data, ref buffer);

                        //TODO убрать логи чтения и записи
                        //WriteToLog($"Sector '{controlSector}':[{blockInSector}]{data.ByteArrayToString()}");
                        //WriteDataToLog(controlSector, blockInSector, data.ByteArrayToString(), false);

                        return((int)ErrorCodes.E_SUCCESS);
                    }
                    return((int)ErrorCodes.E_GENERIC);
                }
                WriteToLog($"ReadBlock ERROR !!! reader:{_reader} card: {_card}\r\n");
                return((int)ErrorCodes.E_CARDREADER_NOT_INIT);
            }
            catch (Exception e)
            {
                WriteToLog($"ReadBlock ERROR !!! {text}\r\n {e}");
                return((int)ErrorCodes.E_GENERIC);
            }
        }
Ejemplo n.º 9
0
        // ОПЕРАЦИЯ ПО КАРТЕ
        /// <summary>
        /// ОПЕРАЦИЯ ПО КАРТЕ
        /// </summary>
        /// <param name="type">тип операции</param>
        /// <param name="terminal">терминал (азс)</param>
        /// <param name="transact">номер транзакции</param>
        /// <param name="opItem">параметры операции</param>
        /// <returns></returns>
        public static ServioCardInfo CardOperationExecute(CardOperationType type, int terminal, long transact, CardOperationItem opItem)
        {
            ServioCardInfo res = new ServioCardInfo {
                ErrorCore = -1, CardNumber = "", IssuerID = -1
            };
            IntPtr obj = new IntPtr();

            IntPtr serialNumberPtr = Marshal.AllocHGlobal(sizeof(SerialnumberT));
            IntPtr cardImagePtr    = Marshal.AllocHGlobal(sizeof(Mf1S70T));
            IntPtr operationPtr    = CardOperation_Create();

            try
            {
                if ((res.ErrorCore = InitInternal(_config, ref obj)) != (int)ErrorCodes.ESuccess)
                {
                    if (res.ErrorCore == (int)ErrorCodes.ECancel)
                    {
                        return(res);
                    }
                    throw new CardShellException("Error Init No" + res, res.ErrorCore);
                }
                UnMemory <byte> .SaveInMemArr(new byte[Mf1S70T.Size], ref cardImagePtr);

                if ((res.ErrorCore = ReadCard(obj, serialNumberPtr, cardImagePtr, false)) != (int)ErrorCodes.ESuccess)
                {
                    if (res.ErrorCore == (int)ErrorCodes.ECancel)
                    {
                        return(res);
                    }
                    throw new CardShellException("Error ReadCard No" + res, res.ErrorCore);
                }
                var operation = UnMemory <CardOperation> .ReadInMem(operationPtr);

                SerialnumberT serialNumber = UnMemory <SerialnumberT> .ReadInMem(serialNumberPtr);

                operation.Size           = sizeof(CardOperation);
                operation.OpCode         = (byte)OperationSelector(type);
                operation.POS            = terminal;                // Номер АЗС или терминала
                operation.OpTime         = DateTime.Now.ToOADate(); // Реальное время с вашего терминала
                operation.TransactID     = transact;                // Тут желательно ваш код код транзакции указать
                operation.CardType       = (int)CardType.CtPayment; // Предположим что тип карты неизвестен
                operation.SerialNumber   = serialNumber;            // Указать серийный номер, считанный с метки
                operation.IssuerID       = -1;                      // Указать -1, программа сама переопределит. Если указать другой код - программа будет использовать его
                operation.CardNumber     = "";                      // Не указывать !!!
                operation.AddPrefixZeros = 0;                       // Нужна доп. настройка. Аналогичная нашей опции в обработчиках
                operation.ItemCount      = 1;                       // При аутентификации позиции не заполнять.

                IntPtr pItem1 = Marshal.AllocHGlobal(sizeof(CardOperationItem));
                UnMemory <CardOperationItem> .SaveInMem(opItem, ref pItem1);

                IntPtr ppItem1 = Marshal.AllocHGlobal(sizeof(IntPtr));
                UnMemory <IntPtr> .SaveInMem(pItem1, ref ppItem1);

                operation.Items = ppItem1;

                UnMemory <CardOperation> .SaveInMem(operation, ref operationPtr);

                if ((res.ErrorCore =
                         OperationSelector(type, obj, serialNumberPtr, cardImagePtr, operationPtr))
                    != (int)ErrorCodes.ESuccess)
                {
                    throw new CardShellException("Error Operation No" + res, res.ErrorCore);
                }

                // флаг указывает на то что образ карты был изменен в процессе операции
                // и нужно записать его обратно.
                // Нужно для пополнения карты при просмотре информации
                operation = UnMemory <CardOperation> .ReadInMem(operationPtr);

                if (operation.CardImageChanged != 0)
                {
                    // при ошибке можно попробовать повторить операцию несколько раз 3-10...
                    // если не проходит то это патовая ситуация и для её дальнейшего
                    // разрешения нужно сохранить SerialNumber, CardImage и CardInfo
                    // В теории, сохранённый SerialNumber и CardImage можно попробовать
                    // записать обратно даже при перезапуске ПО, но до следующего
                    // обслуживания по карте. Чтобы решить ситуацию можно сохранить CardInfo
                    // чтобы в офисе уменьшили или увеличили баланс карты на соотв. значение.
                    if ((res.ErrorCore = WriteCard(obj, serialNumberPtr, cardImagePtr)) != (int)ErrorCodes.ESuccess)
                    {
                        throw new CardShellException("Error WriteCard No" + res, res.ErrorCore);
                    }
                }

                operation    = (CardOperation)Marshal.PtrToStructure(operationPtr, typeof(CardOperation));
                res.CardInfo = operation.CheckImage;
                return(res);
            }
            finally
            {
                //CardOperation_Free(operationPtr);
                UnMemory.FreeIntPtr(serialNumberPtr);
                UnMemory.FreeIntPtr(cardImagePtr);
                //MarshalHelper.UnMemory.FreeIntPtr(operationPtr);
            }
        }
Ejemplo n.º 10
0
        // АВТОРИЗАЦИЯ
        public static ServioCardInfo Authorize()
        {
            ServioCardInfo res = new ServioCardInfo {
                ErrorCore = -1, CardNumber = "", IssuerID = -1
            };
            IntPtr obj = new IntPtr();

            IntPtr serialNumberPtr = Marshal.AllocHGlobal(sizeof(SerialnumberT));
            IntPtr cardImagePtr    = Marshal.AllocHGlobal(sizeof(Mf1S70T));
            IntPtr operationPtr    = CardOperation_Create();

            try
            {
                if ((res.ErrorCore = InitInternal(_config, ref obj)) != (int)ErrorCodes.ESuccess)
                {
                    if (res.ErrorCore == (int)ErrorCodes.ECancel)
                    {
                        return(res);
                    }
                    throw new CardShellException("Error Init No" + res, res.ErrorCore);
                }
                if ((res.ErrorCore = ReadCard(obj, serialNumberPtr, cardImagePtr, true)) != (int)ErrorCodes.ESuccess)
                {
                    if (res.ErrorCore == (int)ErrorCodes.ECancel)
                    {
                        return(res);
                    }
                    throw new CardShellException("Error ReadCard No" + res, res.ErrorCore);
                }

                var operation = UnMemory <CardOperation> .ReadInMem(operationPtr);

                SerialnumberT serialNumber = UnMemory <SerialnumberT> .ReadInMem(serialNumberPtr);

                operation.Size         = sizeof(CardOperation);
                operation.POS          = 1;                       // Номер АЗС или терминала
                operation.OpTime       = DateTime.Now.ToOADate(); // Реальное время с вашего терминала
                operation.TransactID   = 0;                       // Тут желательно ваш код код транзакции указать
                operation.OpCode       = (byte)OpCode.OpAuthorization;
                operation.IsPostpay    = 0;                       // как есть - если постоплата - указать true
                operation.CardType     = (int)CardType.Unknown;   // Предположим что тип карты неизвестен
                operation.SerialNumber = serialNumber;            // Указать серийный номер, считанный с метки
                operation.IssuerID     = -1;
                // Указать -1, программа сама переопределит. Если указать другой код - программа будет использовать его
                operation.CardNumber     = ""; // Не указывать !!!
                operation.AddPrefixZeros = 0;  // Нужна доп. настройка. Аналогичная нашей опции в обработчиках
                operation.WoCard         = 0;  //
                operation.PINChecked     = 0;
                // Если указать false то драйвер запросит форму ввода пароля через callback в случае, если на карту поставили PIN-код
                operation.ItemCount = 0; // Позиции не нужны

                UnMemory <CardOperation> .SaveInMem(operation, ref operationPtr);

                if ((res.ErrorCore = Auth(obj, serialNumberPtr, cardImagePtr, operationPtr)) !=
                    (int)ErrorCodes.ESuccess)
                {
                    if (res.ErrorCore == (int)ErrorCodes.ECancel)
                    {
                        return(res);
                    }
                    throw new CardShellException("Error Auth No" + res, res.ErrorCore);
                }
                operation = UnMemory <CardOperation> .ReadInMem(operationPtr);

                res.IssuerID   = operation.IssuerID;
                res.CardNumber = operation.CardNumber.PadLeft(20, '0');
                return(res);
            }
            catch (CardShellException ex)
            {
                return(new ServioCardInfo {
                    ErrorCore = ex.ErrorCode
                });
            }
            catch
            {
                return(new ServioCardInfo {
                    ErrorCore = (int)ErrorCodes.EGeneric,
                });
            }
            finally
            {
                UnMemory.FreeIntPtr(serialNumberPtr);
                UnMemory.FreeIntPtr(cardImagePtr);
                //MarshalHelper.UnMemory.FreeIntPtr(operationPtr);
                CardOperation_Free(operationPtr);
            }
        }
Ejemplo n.º 11
0
        public static ServioCardInfo ReadCardNumber()
        {
            ServioCardInfo res = new ServioCardInfo {
                ErrorCore = -1, CardNumber = "", IssuerID = -1
            };
            IntPtr obj = new IntPtr();

            if ((res.ErrorCore = InitInternal(_config, ref obj)) != 0)
            {
                throw new CardShellException("Error Init No" + res, res.ErrorCore);
            }

            IntPtr serialNumberPtr = Marshal.AllocHGlobal(sizeof(SerialnumberT));
            IntPtr cardImagePtr    = Marshal.AllocHGlobal(sizeof(Mf1S70T));
            IntPtr operationPtr    = CardOperation_Create();

            try
            {
                if ((res.ErrorCore = ReadCard(obj, serialNumberPtr, cardImagePtr, true)) != 0)
                {
                    throw new CardShellException("Error ReadCard No" + res, res.ErrorCore);
                }
                //Operation = MarshalHelper.UnMemory<TCardOperation>.ReadInMem(OperationPtr);
                //var op = Operation.CheckImage;
                //SERIALNUMBER_T SerialNumber = MarshalHelper.UnMemory<SERIALNUMBER_T>.ReadInMem(SerialNumberPtr);
                //var ser = SerialNumber.getSerial();

                //Operation.POSName = "TestTestTest";
                //Operation.Size = sizeof(TCardOperation);
                //Operation.POS = 1;
                //Operation.OpTime = DateTime.Now.ToOADate();
                //Operation.IsPostpay = 0;
                //Operation.CardType = 2;
                //Operation.SerialNumber = SerialNumber;
                //Operation.CardNumber = null;
                //Operation.IssuerID = -1;
                //Operation.AddPrefixZeros = 0;
                //Operation.WoCard = 0;
                //Operation.PINChecked = 1;
                //Operation.ItemCount = 0;
                //MarshalHelper.UnMemory<TCardOperation>.SaveInMem(Operation, ref OperationPtr);

                if ((res.ErrorCore = Auth(obj, serialNumberPtr, cardImagePtr, operationPtr)) != 0)
                {
                    throw new CardShellException("Error Auth No" + res, res.ErrorCore);
                }

                var operation = UnMemory <CardOperation> .ReadInMem(operationPtr);

                //var op = Operation.CheckImage;
                //SerialNumber = MarshalHelper.UnMemory<SERIALNUMBER_T>.ReadInMem(SerialNumberPtr);
                //var ser = SerialNumber.getSerial();

                //Operation = (TCardOperation)Marshal.PtrToStructure(OperationPtr, typeof(TCardOperation));
                res.IssuerID   = operation.IssuerID;
                res.CardNumber = operation.CardNumber.PadLeft(20, '0');
            }
            finally
            {
                UnMemory.FreeIntPtr(serialNumberPtr);
                UnMemory.FreeIntPtr(cardImagePtr);
                //MarshalHelper.UnMemory.FreeIntPtr(operationPtr);
                CardOperation_Free(operationPtr);
            }
            return(res);
        }