Пример #1
0
        // This function is thread-safe and could be called by a few threads simoltaneously.
        // If FieldName parameter is NULL, a new field will be created, otherwise existing field will be signed
        // and all field-related parameters will be ignored
        public static void SAPI_sign_file(string FileName, string FieldName, string User, string Password, string SignPassword,
                                          int page, int x, int y, int height, int width,
                                          bool Invisible, string Reason, int AppearanceMask, string NewFieldName, string GraphImgName)
        {
            int            rc;
            SESHandle      SesHandle;
            SigFieldHandle sf = null;

            SAPICrypt SAPI = new SAPICryptClass();

            if ((rc = SAPI.HandleAcquire(out SesHandle)) != 0)
            {
                throw new Exception("Failed in SAPIHandleAcquire() with rc = " + rc.ToString("X"));
            }

            //Logon
            if ((rc = SAPI.Logon(SesHandle, User, null, Password)) != 0)
            {
                SAPI.HandleRelease(SesHandle);
                throw new Exception("Failed to authenticate user with rc = " + rc.ToString("X"));
            }


            //Set Graphical Image if required
            if (GraphImgName != null && GraphImgName.Length > 1)
            {
                SAPIContext ctxGraphImg = new SAPIContextClass();

                //Start Graphical Images Enumeration
                if ((rc = SAPI.GraphicSigImageEnumInit(SesHandle, ctxGraphImg, AR_GR_SIG_DATA_FORMAT_ALL, 0)) != 0)
                {
                    SAPI.Logoff(SesHandle);
                    SAPI.HandleRelease(SesHandle);
                    throw new Exception("Failed to enumerate graphical signatures with rc = " + rc.ToString());
                }

                GraphicImageHandle hGrImg = null;
                bool isFound = false;
                while (((uint)(rc = SAPI.GraphicSigImageEnumCont(SesHandle, ctxGraphImg, out hGrImg))) != SAPI_ERROR_NO_MORE_ITEMS)
                {
                    if (rc != 0)
                    {
                        SAPI.ContextRelease(ctxGraphImg);
                        SAPI.Logoff(SesHandle);
                        SAPI.HandleRelease(SesHandle);
                        throw new Exception("Failed to retrieve next graphical signature with rc = " + rc.ToString());
                    }

                    //Get Graphical Signature Info
                    GraphicImageInfo giInfo = null;
                    if ((rc = SAPI.GraphicSigImageInfoGet(SesHandle, hGrImg, out giInfo,
                                                          SAPI_ENUM_GRAPHIC_IMAGE_FORMAT.SAPI_ENUM_GRAPHIC_IMAGE_NONE, 0)) != 0)
                    {
                        SAPI.ContextRelease(ctxGraphImg);
                        SAPI.HandleRelease(hGrImg);
                        SAPI.Logoff(SesHandle);
                        SAPI.HandleRelease(SesHandle);
                        throw new Exception("Failed to retrieve graphical signature info with rc = " + rc.ToString());
                    }

                    //Check if required Graphical image has been found
                    if (giInfo.Name.Trim().ToLower() == GraphImgName.Trim().ToLower())
                    {
                        //If found - set is as default Graph. Image
                        if ((rc = SAPI.GraphicSigImageSetDefault(SesHandle, hGrImg)) != 0)
                        {
                            SAPI.ContextRelease(ctxGraphImg);
                            SAPI.HandleRelease(hGrImg);
                            SAPI.Logoff(SesHandle);
                            SAPI.HandleRelease(SesHandle);
                            throw new Exception("Failed to define default graphical signature with rc = " + rc.ToString());
                        }

                        isFound = true;
                        SAPI.ContextRelease(ctxGraphImg);
                        SAPI.HandleRelease(hGrImg);
                        break;
                    }

                    SAPI.HandleRelease(hGrImg);
                }

                SAPI.ContextRelease(ctxGraphImg);

                //If required Graph Image wasn't found...
                if (!isFound)
                {
                    SAPI.Logoff(SesHandle);
                    SAPI.HandleRelease(SesHandle);
                    throw new Exception("Failed to find Graphical Image with name: " + GraphImgName);
                }
            }


            //Create new signature field
            if (FieldName == null)
            {
                SigFieldSettingsClass SFS = new SigFieldSettingsClass();
                TimeFormatClass       TF  = new TimeFormatClass();
                int Flags = 0;

                //Define name of the new signature field
                if (NewFieldName.Length > 0)
                {
                    SFS.Name = NewFieldName;
                    Flags   |= AR_PDF_FLAG_FIELD_NAME_SET;
                }


                if (Invisible)
                {
                    SFS.Invisible = 1;
                    SFS.Page      = -1;
                }
                else
                {
                    // VISIBLE:
                    SFS.Invisible = 0;
                    // location:
                    SFS.Page   = page;
                    SFS.X      = x;
                    SFS.Y      = y;
                    SFS.Height = height;
                    SFS.Width  = width;
                    // appearance:
                    SFS.AppearanceMask = AppearanceMask;
                    SFS.LabelsMask     = AppearanceMask;
                    SFS.DependencyMode = SAPI_ENUM_DEPENDENCY_MODE.SAPI_ENUM_DEPENDENCY_MODE_INDEPENDENT;
                    SFS.SignatureType  = SAPI_ENUM_SIGNATURE_TYPE.SAPI_ENUM_SIGNATURE_DIGITAL;
                    SFS.Flags          = 0;
                    // time:
                    TF.DateFormat    = "dd MMM yyyy";
                    TF.TimeFormat    = "hh:mm:ss";
                    TF.ExtTimeFormat = SAPI_ENUM_EXTENDED_TIME_FORMAT.SAPI_ENUM_EXTENDED_TIME_FORMAT_NONE;
                    SFS.TimeFormat   = TF;
                }

                //Create the Field
                if ((rc = SAPI.SignatureFieldCreate(SesHandle, SAPI_ENUM_FILE_TYPE.SAPI_ENUM_FILE_ADOBE,
                                                    FileName, SFS, Flags, out sf)) != 0)
                {
                    SAPI.Logoff(SesHandle);
                    SAPI.HandleRelease(SesHandle);
                    throw new Exception("Failed to create new signature field with rc = " + rc.ToString("X"));
                }
            }

            //Find an existing signature field by name
            else
            {
                SAPIContext ctxField    = new SAPIContextClass();
                int         NumOfFields = 0;


                //Initiate the Signature Fields enumeration process
                if ((rc = SAPI.SignatureFieldEnumInit(SesHandle, ctxField, SAPI_ENUM_FILE_TYPE.SAPI_ENUM_FILE_ADOBE,
                                                      FileName, 0, ref NumOfFields)) != 0)
                {
                    SAPI.Logoff(SesHandle);
                    SAPI.HandleRelease(SesHandle);
                    throw new Exception("Failed to start signature field enumeration with rc = " + rc.ToString("X"));
                }


                bool isFound = false;
                for (int i = 0; i < NumOfFields; i++)
                {
                    //Get Next field's handle
                    if ((rc = SAPI.SignatureFieldEnumCont(SesHandle, ctxField, out sf)) != 0)
                    {
                        SAPI.ContextRelease(ctxField);
                        SAPI.Logoff(SesHandle);
                        SAPI.HandleRelease(SesHandle);
                        throw new Exception("Failed in signature fields enumeration with rc = " + rc.ToString("X"));
                    }

                    //Retrieve Signature Field's info
                    SigFieldSettings sfs = new SigFieldSettingsClass();
                    SigFieldInfo     sfi = new SigFieldInfoClass();
                    if ((rc = SAPI.SignatureFieldInfoGet(SesHandle, sf, sfs, sfi)) != 0)
                    {
                        SAPI.HandleRelease(sf);
                        SAPI.ContextRelease(ctxField);
                        SAPI.Logoff(SesHandle);
                        SAPI.HandleRelease(SesHandle);
                        throw new Exception("Failed to retrieve signature field details with rc = " + rc.ToString("X"));
                    }


                    //Check that the field we've found is not signed. If Signed - just skip it.
                    if (sfi.IsSigned != 0)
                    {
                        continue;
                    }

                    if (sfs.Name == FieldName)
                    {
                        SAPI.ContextRelease(ctxField);
                        isFound = true;
                        break;
                    }

                    //Release handle of irrelevant signature field
                    SAPI.HandleRelease(sf);
                }

                if (!isFound)
                {
                    SAPI.ContextRelease(ctxField);
                    SAPI.Logoff(SesHandle);
                    SAPI.HandleRelease(SesHandle);
                    throw new Exception("The file doesn't contain any signature field named: " + FieldName);
                }
            }

            //Define the Reason
            if ((rc = SAPI.ConfigurationValueSet(SesHandle, SAPI_ENUM_CONF_ID.SAPI_ENUM_CONF_ID_REASON,
                                                 SAPI_ENUM_DATA_TYPE.SAPI_ENUM_DATA_TYPE_STR, Reason, 1)) != 0)
            {
                SAPI.HandleRelease(sf);
                SAPI.Logoff(SesHandle);
                SAPI.HandleRelease(SesHandle);
                throw new Exception("Failed in SAPIConfigurationValueSet with rc = " + rc.ToString("X"));
            }

            if (string.IsNullOrEmpty(SignPassword))
            {
                //Prompt-for-sign mode is disabled
                rc = SAPI.SignatureFieldSign(SesHandle, sf, 0);
            }
            else
            {
                //Prompt-for-sign mode is enabled
                rc = SAPI.SignatureFieldSignEx(SesHandle, sf, 0, SignPassword);
            }

            if (rc != 0)
            {
                SAPI.Logoff(SesHandle);
                SAPI.HandleRelease(sf);
                SAPI.HandleRelease(SesHandle);
                throw new Exception("Failed to Sign signature field with rc = " + rc.ToString("X"));
            }

            SAPI.Logoff(SesHandle);
            SAPI.HandleRelease(sf);
            SAPI.HandleRelease(SesHandle);
            return;
        }
        // This function is thread-safe and could be called by a few threads simoltaneously.
        // If FieldName parameter is NULL, a new field will be created, otherwise existing field will be signed
        // and all field-related parameters will be ignored
        public static void SAPI_sign_file(string FileName, string FieldName, string User, string Password, string SignPassword,
									int page, int x, int y, int height, int width,
                                    bool Invisible, string Reason, int AppearanceMask, string NewFieldName, string GraphImgName)
        {
            int rc;
            SESHandle SesHandle;
            SigFieldHandle sf = null;

            SAPICrypt SAPI = new SAPICryptClass();

            if ((rc = SAPI.HandleAcquire(out SesHandle)) != 0) throw new Exception("Failed in SAPIHandleAcquire() with rc = " + rc.ToString("X"));

            //Logon
            if ((rc = SAPI.Logon(SesHandle, User, null, Password)) != 0)
            {
                SAPI.HandleRelease(SesHandle);
                throw new Exception("Failed to authenticate user with rc = " + rc.ToString("X"));
            }

            //Set Graphical Image if required
            if (GraphImgName != null && GraphImgName.Length > 1)
            {

                SAPIContext ctxGraphImg = new SAPIContextClass();

                //Start Graphical Images Enumeration
                if ((rc = SAPI.GraphicSigImageEnumInit(SesHandle, ctxGraphImg, AR_GR_SIG_DATA_FORMAT_ALL, 0)) != 0)
                {
                    SAPI.Logoff(SesHandle);
                    SAPI.HandleRelease(SesHandle);
                    throw new Exception("Failed to enumerate graphical signatures with rc = " + rc.ToString());
                }

                GraphicImageHandle hGrImg = null;
                bool isFound = false;
                while (((uint)(rc = SAPI.GraphicSigImageEnumCont(SesHandle, ctxGraphImg, out hGrImg))) != SAPI_ERROR_NO_MORE_ITEMS)
                {
                    if (rc != 0)
                    {
                        SAPI.ContextRelease(ctxGraphImg);
                        SAPI.Logoff(SesHandle);
                        SAPI.HandleRelease(SesHandle);
                        throw new Exception("Failed to retrieve next graphical signature with rc = " + rc.ToString());
                    }

                    //Get Graphical Signature Info
                    GraphicImageInfo giInfo = null;
                    if ((rc = SAPI.GraphicSigImageInfoGet(SesHandle, hGrImg, out giInfo,
                        SAPI_ENUM_GRAPHIC_IMAGE_FORMAT.SAPI_ENUM_GRAPHIC_IMAGE_NONE, 0)) != 0)
                    {
                        SAPI.ContextRelease(ctxGraphImg);
                        SAPI.HandleRelease(hGrImg);
                        SAPI.Logoff(SesHandle);
                        SAPI.HandleRelease(SesHandle);
                        throw new Exception("Failed to retrieve graphical signature info with rc = " + rc.ToString());
                    }

                    //Check if required Graphical image has been found
                    if (giInfo.Name.Trim().ToLower() == GraphImgName.Trim().ToLower())
                    {

                        //If found - set is as default Graph. Image
                        if ((rc = SAPI.GraphicSigImageSetDefault(SesHandle, hGrImg)) != 0)
                        {
                            SAPI.ContextRelease(ctxGraphImg);
                            SAPI.HandleRelease(hGrImg);
                            SAPI.Logoff(SesHandle);
                            SAPI.HandleRelease(SesHandle);
                            throw new Exception("Failed to define default graphical signature with rc = " + rc.ToString());
                        }

                        isFound = true;
                        SAPI.ContextRelease(ctxGraphImg);
                        SAPI.HandleRelease(hGrImg);
                        break;
                    }

                    SAPI.HandleRelease(hGrImg);
                }

                SAPI.ContextRelease(ctxGraphImg);

                //If required Graph Image wasn't found...
                if (!isFound)
                {
                    SAPI.Logoff(SesHandle);
                    SAPI.HandleRelease(SesHandle);
                    throw new Exception("Failed to find Graphical Image with name: " + GraphImgName);
                }

            }

            //Create new signature field
            if (FieldName == null)
            {
                SigFieldSettingsClass SFS = new SigFieldSettingsClass();
                TimeFormatClass TF = new TimeFormatClass();
                int Flags = 0;

                //Define name of the new signature field
                if (NewFieldName.Length > 0)
                {
                    SFS.Name = NewFieldName;
                    Flags |= AR_PDF_FLAG_FIELD_NAME_SET;
                }

                if (Invisible)
                {
                    SFS.Invisible = 1;
                    SFS.Page = -1;
                }
                else
                {
                    // VISIBLE:
                    SFS.Invisible = 0;
                    // location:
                    SFS.Page = page;
                    SFS.X = x;
                    SFS.Y = y;
                    SFS.Height = height;
                    SFS.Width = width;
                    // appearance:
                    SFS.AppearanceMask = AppearanceMask;
                    SFS.LabelsMask = AppearanceMask;
                    SFS.DependencyMode = SAPI_ENUM_DEPENDENCY_MODE.SAPI_ENUM_DEPENDENCY_MODE_INDEPENDENT;
                    SFS.SignatureType = SAPI_ENUM_SIGNATURE_TYPE.SAPI_ENUM_SIGNATURE_DIGITAL;
                    SFS.Flags = 0;
                    // time:
                    TF.DateFormat = "dd MMM yyyy";
                    TF.TimeFormat = "hh:mm:ss";
                    TF.ExtTimeFormat = SAPI_ENUM_EXTENDED_TIME_FORMAT.SAPI_ENUM_EXTENDED_TIME_FORMAT_NONE;
                    SFS.TimeFormat = TF;
                }

                //Create the Field
                if ((rc = SAPI.SignatureFieldCreate(SesHandle, SAPI_ENUM_FILE_TYPE.SAPI_ENUM_FILE_ADOBE,
                    FileName, SFS, Flags, out sf)) != 0)
                {
                    SAPI.Logoff(SesHandle);
                    SAPI.HandleRelease(SesHandle);
                    throw new Exception("Failed to create new signature field with rc = " + rc.ToString("X"));
                }

            }

            //Find an existing signature field by name
            else
            {

                SAPIContext ctxField = new SAPIContextClass();
                int NumOfFields = 0;

                //Initiate the Signature Fields enumeration process
                if ((rc = SAPI.SignatureFieldEnumInit(SesHandle, ctxField, SAPI_ENUM_FILE_TYPE.SAPI_ENUM_FILE_ADOBE,
                    FileName, 0, ref NumOfFields)) != 0)
                {
                    SAPI.Logoff(SesHandle);
                    SAPI.HandleRelease(SesHandle);
                    throw new Exception("Failed to start signature field enumeration with rc = " + rc.ToString("X"));
                }

                bool isFound = false;
                for (int i = 0; i < NumOfFields; i++)
                {

                    //Get Next field's handle
                    if ((rc = SAPI.SignatureFieldEnumCont(SesHandle, ctxField, out sf)) != 0)
                    {
                        SAPI.ContextRelease(ctxField);
                        SAPI.Logoff(SesHandle);
                        SAPI.HandleRelease(SesHandle);
                        throw new Exception("Failed in signature fields enumeration with rc = " + rc.ToString("X"));
                    }

                    //Retrieve Signature Field's info
                    SigFieldSettings sfs = new SigFieldSettingsClass();
                    SigFieldInfo sfi = new SigFieldInfoClass();
                    if ((rc = SAPI.SignatureFieldInfoGet(SesHandle, sf, sfs, sfi)) != 0)
                    {
                        SAPI.HandleRelease(sf);
                        SAPI.ContextRelease(ctxField);
                        SAPI.Logoff(SesHandle);
                        SAPI.HandleRelease(SesHandle);
                        throw new Exception("Failed to retrieve signature field details with rc = " + rc.ToString("X"));
                    }

                    //Check that the field we've found is not signed. If Signed - just skip it.
                    if (sfi.IsSigned != 0) continue;

                    if (sfs.Name == FieldName)
                    {
                        SAPI.ContextRelease(ctxField);
                        isFound = true;
                        break;
                    }

                    //Release handle of irrelevant signature field
                    SAPI.HandleRelease(sf);

                }

                if (!isFound)
                {
                    SAPI.ContextRelease(ctxField);
                    SAPI.Logoff(SesHandle);
                    SAPI.HandleRelease(SesHandle);
                    throw new Exception("The file doesn't contain any signature field named: " + FieldName);
                }

            }

            //Define the Reason
            if ((rc = SAPI.ConfigurationValueSet(SesHandle, SAPI_ENUM_CONF_ID.SAPI_ENUM_CONF_ID_REASON,
                SAPI_ENUM_DATA_TYPE.SAPI_ENUM_DATA_TYPE_STR, Reason, 1)) != 0)
            {
                SAPI.HandleRelease(sf);
                SAPI.Logoff(SesHandle);
                SAPI.HandleRelease(SesHandle);
                throw new Exception("Failed in SAPIConfigurationValueSet with rc = " + rc.ToString("X"));
            }

            if (string.IsNullOrEmpty(SignPassword))
            {
                //Prompt-for-sign mode is disabled
                rc = SAPI.SignatureFieldSign(SesHandle, sf, 0);
            }
            else
            {
                //Prompt-for-sign mode is enabled
                rc = SAPI.SignatureFieldSignEx(SesHandle, sf, 0, SignPassword);
            }

            if (rc != 0)
            {
                SAPI.Logoff(SesHandle);
                SAPI.HandleRelease(sf);
                SAPI.HandleRelease(SesHandle);
                throw new Exception("Failed to Sign signature field with rc = " + rc.ToString("X"));
            }

            SAPI.Logoff(SesHandle);
            SAPI.HandleRelease(sf);
            SAPI.HandleRelease(SesHandle);
            return;
        }
Пример #3
0
        public static void SignPDF(
            string filePath,
            string username,
            string domain,
            string password,
            int sigPageNum,
            int sigX,
            int sigY,
            int sigWidth,
            int sigHeight,
            string title)
        {
            const int SAPI_OK = 0;
            const int AR_PDF_FLAG_FILESIGN_VERTICAL = 0x00000020;

            int                rc;
            SAPICrypt          SAPI         = new SAPICryptClass();
            SESHandle          sesHandle    = null;
            GraphicImageHandle grpImgHandle = null;

            try
            {
                // Initialize SAPI library
                if ((rc = SAPI.Init()) != SAPI_OK)
                {
                    throw new Exception(string.Format("Failed to initialize SAPI ({0})", rc.ToString("X")));
                }

                // Acquire SAPI session handle
                if ((rc = SAPI.HandleAcquire(out sesHandle)) != SAPI_OK)
                {
                    throw new Exception(string.Format("Failed in SAPIHandleAcquire() ({0})", rc.ToString("X")));
                }

                // Personalize SAPI Session
                if ((rc = SAPI.Logon(sesHandle, username, domain, password)) != SAPI_OK)
                {
                    throw new Exception(string.Format("Failed to authenticate user ({0})", rc.ToString("X")));
                }

                // If the user has more than one graphical signatures, this function opens a new dialog window enabling the user to view and select an image with which to sign.
                if ((rc = SAPI.GraphicSigImageGUISelect(sesHandle, (int)0xFF, 0, SAPI_ENUM_GR_IMG_SELECT_MODE.SAPI_ENUM_GR_IMG_SEL_MODE_SELECT, out grpImgHandle)) != SAPI_OK)
                {
                    throw new Exception(string.Format("Failed in SAPIGraphicSigImageGUISelect() ({0})", rc.ToString("X")));
                }

                // Set the graphical image associated with the graphic image handle as the default graphic signature image
                if ((rc = SAPI.GraphicSigImageSetDefaultEx(sesHandle, grpImgHandle, 0)) != SAPI_OK)
                {
                    throw new Exception(string.Format("Failed in SAPIGraphicSigImageSetDefaultEx() ({0})", rc.ToString("X")));
                }

                SigFieldSettingsClass SFS = new SigFieldSettingsClass();
                TimeFormatClass       TF  = new TimeFormatClass();

                // Define signature field settings
                SFS.Page           = sigPageNum;
                SFS.X              = sigX;
                SFS.Y              = sigY;
                SFS.Width          = sigWidth;
                SFS.Height         = sigHeight;
                SFS.AppearanceMask = (int)SAPI_ENUM_DRAWING_ELEMENT.SAPI_ENUM_DRAWING_ELEMENT_GRAPHICAL_IMAGE |
                                     (int)SAPI_ENUM_DRAWING_ELEMENT.SAPI_ENUM_DRAWING_ELEMENT_SIGNED_BY |
                                     (int)SAPI_ENUM_DRAWING_ELEMENT.SAPI_ENUM_DRAWING_ELEMENT_TIME;
                SFS.SignatureType  = SAPI_ENUM_SIGNATURE_TYPE.SAPI_ENUM_SIGNATURE_DIGITAL;
                SFS.DependencyMode = SAPI_ENUM_DEPENDENCY_MODE.SAPI_ENUM_DEPENDENCY_MODE_INDEPENDENT;
                TF.DateFormat      = "dd/MM/yyyy";
                TF.TimeFormat      = "hh:mm:ss";
                TF.ExtTimeFormat   = SAPI_ENUM_EXTENDED_TIME_FORMAT.SAPI_ENUM_EXTENDED_TIME_FORMAT_GMT; // Display GMT offset
                SFS.TimeFormat     = TF;

                if (!string.IsNullOrEmpty(title))
                {
                    // Set signer's title
                    if ((rc = SAPI.ConfigurationValueSet(sesHandle, SAPI_ENUM_CONF_ID.SAPI_ENUM_CONF_ID_TITLE, SAPI_ENUM_DATA_TYPE.SAPI_ENUM_DATA_TYPE_WSTR, title, 1)) != SAPI_OK)
                    {
                        throw new Exception(string.Format("Failed in SAPIConfigurationValueSet() ({0})", rc.ToString("X")));
                    }

                    SFS.AppearanceMask |= (int)SAPI_ENUM_DRAWING_ELEMENT.SAPI_ENUM_DRAWING_ELEMENT_TITLE;
                }

                // Create and sign a new signature field in the document
                if (SAPI_OK != (rc = SAPI.SignatureFieldCreateSign(sesHandle, SAPI_ENUM_FILE_TYPE.SAPI_ENUM_FILE_ADOBE, filePath, SFS, AR_PDF_FLAG_FILESIGN_VERTICAL, null)))
                {
                    throw new Exception(string.Format("Failed in SAPISignatureFieldCreateSign() ({0})", rc.ToString("X")));
                }
            }
            catch (Exception ex)
            {
                if (sesHandle != null)
                {
                    SAPI.Logoff(sesHandle);         // Release user context
                    SAPI.HandleRelease(sesHandle);  // Release session handle
                }

                if (grpImgHandle != null)
                {
                    SAPI.HandleRelease(grpImgHandle);
                }

                throw ex;
            }
        }
        public static void SignPDF(
            string filePath,
            string username,
            string domain,
            string password,
            int sigPageNum,
            int sigX,
            int sigY,
            int sigWidth,
            int sigHeight,
            string title)
        {
            const int SAPI_OK = 0;
            const int AR_PDF_FLAG_FILESIGN_VERTICAL = 0x00000020;

            int rc;
            SAPICrypt SAPI = new SAPICryptClass();
            SESHandle sesHandle = null;
            GraphicImageHandle grpImgHandle = null;

            try
            {
                // Initialize SAPI library
                if ((rc = SAPI.Init()) != SAPI_OK)
                {
                    throw new Exception(string.Format("Failed to initialize SAPI ({0})", rc.ToString("X")));
                }

                // Acquire SAPI session handle
                if ((rc = SAPI.HandleAcquire(out sesHandle)) != SAPI_OK)
                {
                    throw new Exception(string.Format("Failed in SAPIHandleAcquire() ({0})", rc.ToString("X")));
                }

                // Personalize SAPI Session
                if ((rc = SAPI.Logon(sesHandle, username, domain, password)) != SAPI_OK)
                {
                    throw new Exception(string.Format("Failed to authenticate user ({0})", rc.ToString("X")));
                }

                // If the user has more than one graphical signatures, this function opens a new dialog window enabling the user to view and select an image with which to sign.
                if ((rc = SAPI.GraphicSigImageGUISelect(sesHandle, (int)0xFF, 0, SAPI_ENUM_GR_IMG_SELECT_MODE.SAPI_ENUM_GR_IMG_SEL_MODE_SELECT, out grpImgHandle)) != SAPI_OK)
                {
                    throw new Exception(string.Format("Failed in SAPIGraphicSigImageGUISelect() ({0})", rc.ToString("X")));
                }

                // Set the graphical image associated with the graphic image handle as the default graphic signature image
                if ((rc = SAPI.GraphicSigImageSetDefaultEx(sesHandle, grpImgHandle, 0)) != SAPI_OK)
                {
                    throw new Exception(string.Format("Failed in SAPIGraphicSigImageSetDefaultEx() ({0})", rc.ToString("X")));
                }

                SigFieldSettingsClass SFS = new SigFieldSettingsClass();
                TimeFormatClass TF = new TimeFormatClass();

                // Define signature field settings
                SFS.Page = sigPageNum;
                SFS.X = sigX;
                SFS.Y = sigY;
                SFS.Width = sigWidth;
                SFS.Height = sigHeight;
                SFS.AppearanceMask = (int)SAPI_ENUM_DRAWING_ELEMENT.SAPI_ENUM_DRAWING_ELEMENT_GRAPHICAL_IMAGE |
                                     (int)SAPI_ENUM_DRAWING_ELEMENT.SAPI_ENUM_DRAWING_ELEMENT_SIGNED_BY |
                                     (int)SAPI_ENUM_DRAWING_ELEMENT.SAPI_ENUM_DRAWING_ELEMENT_TIME;
                SFS.SignatureType = SAPI_ENUM_SIGNATURE_TYPE.SAPI_ENUM_SIGNATURE_DIGITAL;
                SFS.DependencyMode = SAPI_ENUM_DEPENDENCY_MODE.SAPI_ENUM_DEPENDENCY_MODE_INDEPENDENT;
                TF.DateFormat = "dd/MM/yyyy";
                TF.TimeFormat = "hh:mm:ss";
                TF.ExtTimeFormat = SAPI_ENUM_EXTENDED_TIME_FORMAT.SAPI_ENUM_EXTENDED_TIME_FORMAT_GMT; // Display GMT offset
                SFS.TimeFormat = TF;

                if (!string.IsNullOrEmpty(title))
                {
                    // Set signer's title
                    if ((rc = SAPI.ConfigurationValueSet(sesHandle, SAPI_ENUM_CONF_ID.SAPI_ENUM_CONF_ID_TITLE, SAPI_ENUM_DATA_TYPE.SAPI_ENUM_DATA_TYPE_WSTR, title, 1)) != SAPI_OK)
                    {
                        throw new Exception(string.Format("Failed in SAPIConfigurationValueSet() ({0})", rc.ToString("X")));
                    }

                    SFS.AppearanceMask |= (int)SAPI_ENUM_DRAWING_ELEMENT.SAPI_ENUM_DRAWING_ELEMENT_TITLE;
                }

                // Create and sign a new signature field in the document
                if (SAPI_OK != (rc = SAPI.SignatureFieldCreateSign(sesHandle, SAPI_ENUM_FILE_TYPE.SAPI_ENUM_FILE_ADOBE, filePath, SFS, AR_PDF_FLAG_FILESIGN_VERTICAL, null)))
                {
                    throw new Exception(string.Format("Failed in SAPISignatureFieldCreateSign() ({0})", rc.ToString("X")));
                }
            }
            catch (Exception ex)
            {
                if (sesHandle != null)
                {
                    SAPI.Logoff(sesHandle);         // Release user context
                    SAPI.HandleRelease(sesHandle);  // Release session handle
                }

                if (grpImgHandle != null)
                {
                    SAPI.HandleRelease(grpImgHandle);
                }

                throw ex;
            }
        }