home *** CD-ROM | disk | FTP | other *** search
-
- /////////////////////////////////////
- // //
- // Transactions Sample Application //
- // //
- /////////////////////////////////////
-
-
- #define UNICODE // For all MSMQ applications
-
- #include <stdio.h>
-
-
- //------------------------------------------------------------------------------
- // Include MS DTC specific header files.
- //------------------------------------------------------------------------------
- #define INITGUID
- #include <transact.h>
-
- // Because we are compiling in UNICODE, here is a problem with DTC...
- //#include <xolehlp.h>
- extern HRESULT DtcGetTransactionManager(
- LPSTR pszHost,
- LPSTR pszTmName,
- REFIID rid,
- DWORD dwReserved1,
- WORD wcbReserved2,
- void FAR * pvReserved2,
- void** ppvObject ) ;
-
- //------------------------------------------------------------------------------
- // Include ODBC specific header file.
- //------------------------------------------------------------------------------
- #ifndef DBNTWIN32
- #define DBNTWIN32
-
- #include <SQLEXT.h>
-
- // from <odbcss.h>
- #define SQL_COPT_SS_BASE 1200
- #define SQL_COPT_SS_ENLIST_IN_DTC (SQL_COPT_SS_BASE+7) // Enlist in a Viper transaction
-
- // Defines for use with SQL_ENLIST_IN_DTC
- #define SQL_DTC_DONE 0L // Delimits end of Viper transaction
-
- #endif
-
- //--------------------------------------------------------------------------
- // Enable Ansi ODBC on VC5
- //--------------------------------------------------------------------------
-
- #ifdef SQLExecDirect
- #undef SQLExecDirect
- #define SQLExecDirect SQLExecDirectA
- #endif
-
- #ifdef SQLSetConnectOption
- #undef SQLSetConnectOption
- #define SQLSetConnectOption SQLSetConnectOptionA
- #endif
-
- #ifdef SQLError
- #undef SQLError
- #define SQLError SQLErrorA
- #endif
-
- #ifdef SQLConnect
- #undef SQLConnect
- #define SQLConnect SQLConnectA
- #endif
-
- //------------------------------------------------------------------------------
- // Include MSMQ specific header file.
- //------------------------------------------------------------------------------
- #include "mq.h"
-
- //------------------------------------------------------------------------------
- // Define constants
- //------------------------------------------------------------------------------
- #define STR_LEN 40
- #define MAX_VAR 20
- #define MAX_FORMAT 100
-
-
- //------------------------------------------------------------------------------
- // Define datatypes
- //------------------------------------------------------------------------------
- typedef struct DBCONN
- {
- char pszSrv [STR_LEN]; // data source name, configured through control panel
- char pszUser [STR_LEN]; // Login user name
- char pszPasswd[STR_LEN]; // Login user password
- HDBC hdbc; // handle to an ODBC database connection
- HSTMT hstmt; // an ODBC statement handle, for use with SQLExecDirect
-
- } DBCONN;
-
-
- //------------------------------------------------------------------------------
- // Define Globals
- //------------------------------------------------------------------------------
-
- // global DB connection struct for the server
- static DBCONN gSrv =
- { "MSMQDemo",
- "sa",
- "",
- SQL_NULL_HDBC,
- SQL_NULL_HSTMT
- };
-
-
- // guid type for MQTransTest queues
- static CLSID guidMQTransTestType =
- { 0xb856ab1, 0x16b6, 0x11d0, { 0x80, 0x48, 0x0, 0xa0, 0x24, 0x53, 0xc1, 0x6f } };
-
-
- //handle to ODBC environment
- HENV g_hEnv = SQL_NULL_HENV ;
-
-
- //buffer for machine name
- WCHAR g_wszMachineName[ MAX_COMPUTERNAME_LENGTH + 1 ];
-
-
- //--------------------------------------------------------------------------
- // Forward declaration of routines used.
- //--------------------------------------------------------------------------
-
- void LogonToDB(DBCONN *ptr);
- void ExecuteStatement(DBCONN *ptr, char* pszBuf, BOOL ProcessFlag);
- BOOL ProcessRetCode(char* pszFuncName,
- DBCONN *ptr,
- RETCODE retcode,
- BOOL fExit = TRUE);
- void DoSQLError(DBCONN *ptr);
- void FreeODBCHandles(DBCONN *ptr);
- void Error(char *s, HRESULT hr);
- void Syntax();
- void LocateTargetQueue(CLSID *pGuidType, WCHAR wsFormat[MAX_FORMAT]);
- void PrepareSendMessageProperties(MSGPROPID amPropId[MAX_VAR],
- MQPROPVARIANT aPropVar[MAX_VAR],
- MQMSGPROPS &msgprops,
- DWORD &TransferSum);
- void CreateQueue(CLSID *pGuidType, WCHAR wsFormat[]);
- void GetMachineName();
- void DisplayDollars (DBCONN *ptr, char *psAccount);
-
-
- //------------------------------------------------------------------------------
- // SENDER MODE:
- //
- // The Sender side does the following:
- // 1. Creates database "SenderAccount".
- // 2. Locates a MSMQ queue of type MQTransTest and opens it.
- // (NOTE: for simplicity, this sample assumes there's only one queue of this type)
- // 3. In a loop:
- // Prompts the user to enter TransferSum.
- // Creates a transaction using MS DTC.
- // Within the transaction:
- // Updates "SenderAccount" database (subtracts TransferSum).
- // Sends a message to Receiver side.
- // Commits the transaction.
- //
- // 4. Cleanup.
- //
- //
- //
- // The transaction in the Sender mode includes two operations:
- // (1) Update "SenderAccount" database (subtract TransferSum).
- // (2) Send message to Receiver side.
- //------------------------------------------------------------------------------
-
- void Sender()
- {
-
- ITransactionDispenser *pTransactionDispenser;
- ITransaction *pTransaction;
- BOOL fTransactionCommitFlag;
- // used to decide wother to Commit or Abort
-
- HRESULT hr;
- RETCODE retcode;
- DWORD dwTransferSum; // set by user
- char sUserString[ STR_LEN ];
- char sSQLStatement[ STR_LEN*2 ];
-
- MQMSGPROPS msgprops;
- MQPROPVARIANT aPropVar[MAX_VAR];
- MSGPROPID amPropId[MAX_VAR];
- WCHAR wsFormat[MAX_FORMAT];
- QUEUEHANDLE aqh;
-
-
- printf("\nSender Side.\n\n");
-
- //---------------------------------------------------------------------
- // Build "SenderAccount" database (with the sum $1000)
- //---------------------------------------------------------------------
-
- printf ("Building SenderAccount with the sum $1000... ");
-
- // Get ODBC environment handle
- retcode = SQLAllocEnv(&g_hEnv);
-
- ProcessRetCode("SQLAllocEnv",0, retcode);
-
- // Establish connection to database
- LogonToDB(&gSrv);
-
- // Clear database from previous run.
- ExecuteStatement(&gSrv,"DROP TABLE SenderAccount",FALSE);
-
- // Create new table in database
- ExecuteStatement(&gSrv,
- "CREATE TABLE SenderAccount (Rate INTEGER CONSTRAINT c1 CHECK (Rate>=0))",TRUE);
-
- // Insert new data in database
- ExecuteStatement(&gSrv,"INSERT INTO SenderAccount VALUES(1000)",TRUE);
-
- printf ("OK.\n\n");
-
- //-----------------------------------------------------------------------
- // Locate target queue and Open it for send
- //-----------------------------------------------------------------------
-
- printf ("Searching Receiver queue... ");
-
- // Locate target queue
- LocateTargetQueue (&guidMQTransTestType, wsFormat);
-
- // Open target queue
- hr = MQOpenQueue(wsFormat, MQ_SEND_ACCESS, 0, &aqh);
-
- if (FAILED(hr))
- {
- Error ("Open Queue ",hr);
- }
-
- //--------------------------------------------------------------------------
- // Get Transaction Dispenser
- //--------------------------------------------------------------------------
-
- // Obtain an interface pointer from MS DTC proxy
- hr = DtcGetTransactionManager(
- NULL, // pszHost
- NULL, // pszTmName
- IID_ITransactionDispenser, // IID of interface
- 0, // Reserved -- must be null
- 0, // Reserved -- must be null
- 0, // Reserved -- must be null
- (void **)&pTransactionDispenser // pointer to pointer to requested interface
- );
-
- if (FAILED(hr))
- {
- Error ("DTCGetTransactionManager",hr);
- }
-
- //--------------------------------------------------------------------
- // Sender Main Loop
- //--------------------------------------------------------------------
- while (TRUE)
- {
-
- // Prompt user to enter TransferSum
- printf ("\n\nPlease enter the sum of dollars to transfer, or '0' to quit ==> ");
-
- // Read user input
- fgets (sUserString, STR_LEN, stdin);
-
- // Convert user string to DWORD
- dwTransferSum = atoi(sUserString);
-
- // Prepare properties of message to send
- PrepareSendMessageProperties (amPropId,
- aPropVar,
- msgprops,
- dwTransferSum);
-
- //---------------------------------------------------------------------
- // Create transaction (Inside Sender's Main Loop)
- //---------------------------------------------------------------------
-
- printf ("\nStarting transaction...\n\n");
-
- // Initiate an MS DTC transaction
- hr = pTransactionDispenser->BeginTransaction (
- 0, // must be null
- ISOLATIONLEVEL_ISOLATED, // Isolation Level
- ISOFLAG_RETAIN_DONTCARE, // Isolation flags
- 0, // pointer to transaction options object
- &pTransaction); // pointer to pointer to transaction object
-
- if (FAILED(hr))
- {
- Error ("BeginTransaction",hr);
- }
-
- // Default is to commit transaction
- fTransactionCommitFlag = TRUE;
-
- //
- // SQL is a resource manager in the transaction.
- // It must be enlisted.
- //
-
- // Enlist database in the transaction
- retcode = SQLSetConnectOption (gSrv.hdbc,
- SQL_COPT_SS_ENLIST_IN_DTC,
- (UDWORD)pTransaction);
-
- if (retcode != SQL_SUCCESS)
- {
- ProcessRetCode("SQLSetConnection", &gSrv, retcode, FALSE);
- fTransactionCommitFlag = FALSE;
- }
-
-
- // Prepare SQL statement to update SenderAccount
- sprintf (sSQLStatement,
- "UPDATE SenderAccount SET Rate = Rate - %lu", dwTransferSum) ;
-
- // Allocate a statement handle for use with SQLExecDirect
- retcode = SQLAllocStmt(gSrv.hdbc, &gSrv.hstmt);
-
- if (retcode != SQL_SUCCESS)
- {
- ProcessRetCode("SQLAllocStmt", &gSrv, retcode, FALSE);
- fTransactionCommitFlag = FALSE;
- }
-
- // Update database (subtract TransferSum from SenderAccount)
- retcode = SQLExecDirect (gSrv.hstmt,(UCHAR *) sSQLStatement, SQL_NTS);
-
- if (retcode != SQL_SUCCESS)
- {
- ProcessRetCode("SQLExecDirect", &gSrv, retcode, FALSE);
- fTransactionCommitFlag = FALSE;
- }
-
- // Free the statement handle
- retcode = SQLFreeStmt(gSrv.hstmt, SQL_DROP);
-
- gSrv.hstmt = SQL_NULL_HSTMT;
-
- //
- // MSMQ is another resource manager in the transaction.
- // Its enlistment is implicit.
- //
-
- // Within the transaction: Send message to Receiver Side
- hr = MQSendMessage(aqh, // Handle to destination queue
- &msgprops, // pointer to MQMSGPROPS structure
- pTransaction); // pointer to Transaction Object
-
-
- if (FAILED(hr))
- {
- printf("\nFailed in MQSendMessage(). hresult- %lxh\n", (DWORD) hr) ;
- fTransactionCommitFlag = FALSE;
- }
-
-
- // Commit the transaction
- if (fTransactionCommitFlag)
- {
- printf ("Committing the transaction... ");
-
- hr = pTransaction->Commit(0, 0, 0);
-
- if (FAILED(hr))
- printf ("Failed... Transaction aborted.\n\n");
- else
- printf ("Transaction committed successfully.\n\n");
-
- }
- else
- {
- printf ("Aborting the transaction... ");
-
- hr = pTransaction->Abort(0, 0, 0);
-
- if (FAILED(hr))
- Error("Transaction Abort",hr);
- else
- printf ("Transaction aborted.\n\n");
- }
-
- // Release the transaction
- pTransaction->Release();
-
- // End enlistment of database
- retcode = SQLSetConnectOption (gSrv.hdbc, SQL_COPT_SS_ENLIST_IN_DTC, SQL_DTC_DONE);
-
- ProcessRetCode ("SQLSetConnectOption", &gSrv, retcode);
-
- // Display sum of dollars in Sender Account
- DisplayDollars (&gSrv,"SenderAccount");
-
- // quit loop when nothing was transferred.
- if (dwTransferSum == 0)
- break;
- }
-
- //--------------------------------------------------------------------------
- // Cleanup
- //--------------------------------------------------------------------------
-
- // Release Transaction Dispenser
- pTransactionDispenser->Release();
-
-
- // Free database
- ExecuteStatement(&gSrv,"DROP TABLE SenderAccount",TRUE);
-
-
- // Free ODBC handle
- FreeODBCHandles(&gSrv);
-
-
- // Free the ODBC environment handle
- retcode = SQLFreeEnv(g_hEnv);
-
- if (retcode == SQL_ERROR)
- Error ("SQL FreeEnv ",0);
-
-
- // Free MSMQ queue handle
- MQCloseQueue(aqh);
-
-
- printf ("\n\nSender Side completed.\n\n");
-
- }
-
-
-
-
- //------------------------------------------------------------------------------
- // RECEIVER MODE:
- //
- // The Receiver side does the following:
- // 1. Creates database "ReceiverAccount".
- // 2. Creates a MSMQ public queue (with the Transactional property)
- // of type MQTransTest on its own machine and opens it.
- // 3. In a loop:
- // Creates a transaction using MS DTC.
- // Within the transaction:
- // Receives a message from the queue (with the TransferSum).
- // Updates "ReceiverAccount" database (adds TransferSum).
- // Commits the transaction.
- //
- // 4. Cleanup.
- //
- //
- //
- // The transaction in the Receiver mode include two operations:
- // (1) Receive message from queue (sent by Sender Side).
- // (2) Update "ReceiverAccount" database (add TransferSum).
- //------------------------------------------------------------------------------
-
- void Receiver()
- {
- MSGPROPID amPropId[MAX_VAR];
- MQMSGPROPS msgprops;
- MQPROPVARIANT aPropVar[MAX_VAR];
- DWORD cProps;
- HRESULT hr;
- WCHAR wsFormat[MAX_FORMAT];
- QUEUEHANDLE aqh;
-
- ITransactionDispenser *pTransactionDispenser;
- ITransaction *pTransaction;
- BOOL TransactionCommitFlag; // used to decide Commit or Abort
-
- RETCODE retcode;
- DWORD TransferSum;
-
- DWORD MessageBuffer; // message body is the TransferSum
- char sSQLStatement[STR_LEN*2];
-
-
-
-
-
- printf ("\nReceiver Side.\n\n");
-
- //-----------------------------------------------------------------------
- // Build "ReceiverAccount" database (with the rate $500)
- //-----------------------------------------------------------------------
-
- printf ("Building ReceiverAccount with the rate $500... ");
-
- // Get ODBC environment handle
- retcode = SQLAllocEnv(&g_hEnv);
-
- ProcessRetCode("SQLAllocEnv",0, retcode);
-
- // Establish connection to database.
- LogonToDB(&gSrv);
-
- // Clear table from previous run.
- ExecuteStatement(&gSrv,"DROP TABLE ReceiverAccount",FALSE);
-
- // Create new table.
- ExecuteStatement(&gSrv,"CREATE TABLE ReceiverAccount (Rate INTEGER CONSTRAINT c2 CHECK (Rate>0))",TRUE);
-
- // Insert new data in the table.
- ExecuteStatement(&gSrv,"INSERT INTO ReceiverAccount VALUES(500)",TRUE);
-
- printf ("OK.\n\n");
-
- //-----------------------------------------------------------------------
- // Create queue and Open it for receive
- //-----------------------------------------------------------------------
-
- printf ("Creating Receiver queue... ");
-
- // Create the queue
- CreateQueue (&guidMQTransTestType, wsFormat);
-
- // Prepare message properties to read
- cProps = 0;
-
- amPropId[cProps] = PROPID_M_BODY;
-
- aPropVar[cProps].vt = VT_UI1 | VT_VECTOR;
- aPropVar[cProps].caub.cElems = sizeof(MessageBuffer);
- aPropVar[cProps].caub.pElems = (unsigned char *)&MessageBuffer;
- cProps++;
-
- // Create a MSGPROPS structure
- msgprops.cProp = cProps;
- msgprops.aPropID = amPropId;
- msgprops.aPropVar = aPropVar;
- msgprops.aStatus = 0;
-
- // Open the queue
- hr = MQOpenQueue(wsFormat, MQ_RECEIVE_ACCESS, 0, &aqh);
-
- //
- // Little bit tricky. MQCreateQueue succeeded but it does not mean
- // that MQOpenQueue will, because of replication delay. The queue is
- // registered in MQIS, but it might take a replication interval
- // until the replica reach the server I am connected to.
- // To overcome this, open the queue in a loop.
- //
- if (hr == MQ_ERROR_QUEUE_NOT_FOUND)
- {
- int iCount = 0 ;
- while((hr == MQ_ERROR_QUEUE_NOT_FOUND) && (iCount < 120))
- {
- printf(".");
-
- // Wait a bit
- iCount++ ;
- Sleep(500);
-
- // And retry
- hr = MQOpenQueue(wsFormat, MQ_RECEIVE_ACCESS, 0, &aqh);
- }
- }
-
- if (FAILED(hr))
- {
- Error ("Can't OpenQueue", hr);
- }
-
- printf("OK.");
-
-
- //--------------------------------------------------------------------------
- // Get Transaction Dispenser
- //--------------------------------------------------------------------------
-
- // Obtain an interface pointer from MS DTC proxy
- hr = DtcGetTransactionManager(
- NULL, NULL, // pszHost, pszTmName
- IID_ITransactionDispenser, // IID of requested interface
- 0,0,0, // Reserved -- must be null
- (void **)&pTransactionDispenser); // pointer to pointer to requested interface
-
-
- if (FAILED(hr))
- Error ("DTCGetTransactionManager",hr);
-
-
- //--------------------------------------------------------------------------
- // Receiver Main Loop
- //--------------------------------------------------------------------------
- while (TRUE)
- {
-
- printf ("\n\nWaiting for a message to come... ");
-
- // Peek outside the transaction, to avoid database lock
- // for long/infinite period.
- //
- //dwSize = sizeof(wsResponse);
- hr = MQReceiveMessage(
- aqh, // Handle to queue
- INFINITE, // Timeout
- MQ_ACTION_PEEK_CURRENT, // Peek Action
- &msgprops, // Message Properties
- NULL, // Overlap
- NULL, // Receive Callback
- NULL, // Cursor
- NULL // No transaction yet
- );
-
- if (FAILED(hr))
- Error("MQReceiveMessage (PEEKING) ",hr);
-
-
-
- //--------------------------------------------------------------------------
- // Create transaction
- //--------------------------------------------------------------------------
- printf ("\n\nStarting transaction...\n\n");
-
-
- // Initiate an MS DTC transaction
- hr = pTransactionDispenser->BeginTransaction (
- 0, // must be null
- ISOLATIONLEVEL_ISOLATED, // Isolation Level
- ISOFLAG_RETAIN_DONTCARE, // Isolation flags
- 0, // pointer to transaction options object
- &pTransaction); // pointer to pointer to transaction object
-
- if (FAILED(hr))
- Error ("BeginTransaction",hr);
-
-
- // Default is to commit transaction
- TransactionCommitFlag = TRUE;
-
- //
- // SQL is a resource manager in the transaction.
- // It must be enlisted.
- //
-
- // Enlist database in the transaction
- retcode = SQLSetConnectOption (gSrv.hdbc, SQL_COPT_SS_ENLIST_IN_DTC, (UDWORD)pTransaction);
-
- if (retcode != SQL_SUCCESS)
- TransactionCommitFlag = FALSE;
-
-
-
- // Receive the message from the queue
- //dwSize = sizeof(wsResponse);
- hr = MQReceiveMessage(
- aqh, // Handle to queue
- INFINITE, // Timeout
- MQ_ACTION_RECEIVE, // Receive Action
- &msgprops, // Message Properties
- NULL,NULL,NULL, // Overlap, Receive Callback, Cursor
- pTransaction); // pointer to transaction object
-
- if (FAILED(hr))
- TransactionCommitFlag = FALSE;
-
-
- // Message buffer holds the TransferSum
- TransferSum = (DWORD)MessageBuffer;
-
-
- // Prepare SQL statement to update ReceiverAccount
- sprintf (sSQLStatement, "UPDATE ReceiverAccount SET Rate = Rate + %i",TransferSum);
-
-
- // Allocate a statement handle for use with SQLExecDirect
- retcode = SQLAllocStmt(gSrv.hdbc,&gSrv.hstmt);
-
- if (retcode != SQL_SUCCESS)
- TransactionCommitFlag = FALSE;
-
-
- // Update database (add TransferSum to ReceiverAccount)
- retcode = SQLExecDirect (gSrv.hstmt,(UCHAR *) sSQLStatement, SQL_NTS);
-
- if (retcode != SQL_SUCCESS)
- TransactionCommitFlag = FALSE;
-
-
- // Free the statement handle
- retcode = SQLFreeStmt(gSrv.hstmt, SQL_DROP);
-
- gSrv.hstmt = SQL_NULL_HSTMT;
-
-
-
- // Commit the transaction
- if (TransactionCommitFlag)
- {
- printf ("Committing the transaction... ");
-
- hr = pTransaction->Commit(0, 0, 0);
-
- if (FAILED(hr))
- printf ("Failed... Transaction aborted.\n\n");
- else
- printf ("Transaction committed successfully.\n\n");
-
- }
-
-
- // Abort the transaction
- else
- {
- printf ("Aborting the transaction... ");
-
- hr = pTransaction->Abort(0, 0, 0);
-
- if (FAILED(hr))
- Error("Transaction Abort",hr);
- else
- printf ("Transaction aborted.\n\n");
-
- }
-
-
-
- // Release the transaction
- pTransaction->Release();
-
-
- // End enlistment of database
- retcode = SQLSetConnectOption (gSrv.hdbc, SQL_COPT_SS_ENLIST_IN_DTC, SQL_DTC_DONE);
-
- ProcessRetCode ("SQLSetConnectOption", &gSrv, retcode);
-
-
- // Display sum of dollars in Receiver Account
- DisplayDollars (&gSrv, "ReceiverAccount");
-
-
- // Decide if to continue loop
- if (TransferSum == 0)
- break;
-
-
- }
-
-
- //--------------------------------------------------------------------------
- // Cleanup
- //--------------------------------------------------------------------------
-
- // Release Transaction Dispenser
- pTransactionDispenser->Release();
-
-
- // Free database
- ExecuteStatement(&gSrv,"DROP TABLE ReceiverAccount",TRUE);
-
-
- // Free ODBC handle
- FreeODBCHandles(&gSrv);
-
-
- // Free the ODBC environment handle
- retcode = SQLFreeEnv(g_hEnv);
-
- if (retcode == SQL_ERROR)
- Error ("SQL FreeEnv ",0);
-
-
- // Free queue handle
- MQCloseQueue(aqh);
-
-
- // Delete queue from directory
- MQDeleteQueue(wsFormat);
-
-
- printf ("\n\nReceiver Side completed.\n\n");
- }
-
-
-
- //------------------------------------------------------------------------------
- // MAIN
- //------------------------------------------------------------------------------
- main(int argc, char * * argv)
- {
- DWORD dwSize;
-
- if(argc != 2)
- Syntax();
-
-
- // Retrieve machine name
- dwSize = sizeof(g_wszMachineName);
- GetComputerName(g_wszMachineName, &dwSize);
-
-
-
- if(strcmp(argv[1], "-s") == 0)
- Sender();
-
- else if(strcmp(argv[1], "-r") == 0)
- Receiver();
-
- else
- Syntax();
-
- return(1);
-
- }
-
-
-
- //------------------------------------------------------------------------------
- // Subroutines
- //------------------------------------------------------------------------------
-
- void Error(char *s, HRESULT hr)
- {
-
- printf("\n\nError: %s (0x%X) \n", s, hr);
- exit(1);
- }
-
- //------------------------------------------------------------------------------
-
- void Syntax()
- {
- printf("\n");
- printf("Syntax: msmqtrans -s | -r\n");
- printf("\t-s - Sender Side\n");
- printf("\t-r - Receiver Side\n");
- exit(1);
-
- }
-
- //------------------------------------------------------------------------------
-
- void LocateTargetQueue (CLSID *pGuidType, WCHAR wsFormat[MAX_FORMAT])
- {
-
- DWORD dwSize;
- DWORD i;
-
- DWORD cQueue;
- DWORD cProps;
- HRESULT hr;
- MQPROPERTYRESTRICTION aPropRestriction[MAX_VAR];
- MQRESTRICTION Restriction;
- MQCOLUMNSET Column;
- QUEUEPROPID aqPropId[MAX_VAR];
- HANDLE hEnum;
- MQPROPVARIANT aPropVar[MAX_VAR];
-
- //--------------------------------------------------------------------------
- // Prepare Parameters to locate a queue
- //--------------------------------------------------------------------------
-
- // 1. Restriction = All queue with PROPID_TYPE
- // equal the type of MQTransTest queue.
- cProps = 0;
-
- aPropRestriction[cProps].rel = PREQ;
- aPropRestriction[cProps].prop = PROPID_Q_TYPE;
- aPropRestriction[cProps].prval.vt = VT_CLSID;
- aPropRestriction[cProps].prval.puuid = pGuidType;
- cProps++;
-
- Restriction.cRes = cProps;
- Restriction.paPropRes = aPropRestriction;
-
-
- // 2. Columnset (In other words what property I want to retrieve).
- // Only the instance is important.
- cProps = 0;
- aqPropId[cProps] = PROPID_Q_INSTANCE;
- cProps++;
-
- Column.cCol = cProps;
- Column.aCol = aqPropId;
-
- //--------------------------------------------------------------------------
- // Locate the queues. Issue the query
- //--------------------------------------------------------------------------
- hr = MQLocateBegin(NULL,&Restriction,&Column,NULL,&hEnum);
-
- if (FAILED(hr))
- Error ("Locate Begin ",hr);
-
-
- //--------------------------------------------------------------------------
- // Get the results
- //--------------------------------------------------------------------------
- cQueue = MAX_VAR;
- hr = MQLocateNext(hEnum, &cQueue, aPropVar);
-
- if (FAILED(hr))
- Error ("MQLocateNext ",hr);
-
- hr = MQLocateEnd(hEnum);
-
- if(cQueue == 0)
- {
- // Could Not find any queue, so exit
- printf("NOT FOUND... exiting.\n\n");
- exit(0);
- }
-
-
- printf("FOUND.", cQueue);
-
- dwSize = sizeof(WCHAR)*MAX_FORMAT;
-
- //Transform the Instance GUID to format name
- hr = MQInstanceToFormatName(aPropVar[0].puuid, wsFormat, &dwSize);
-
- if (FAILED(hr))
- Error ("Guidto Format Name ",hr);
-
-
- // Free the GUID memory that was allocated during the locate
- for(i = 0; i < cQueue; i++)
- MQFreeMemory(aPropVar[i].puuid);
-
-
- }
-
-
- //------------------------------------------------------------------------------
-
- void PrepareSendMessageProperties (MSGPROPID amPropId[MAX_VAR],
- MQPROPVARIANT aPropVar[MAX_VAR],
- MQMSGPROPS &msgprops,
- DWORD &TransferSum)
- {
-
- DWORD cProps;
-
- cProps = 0;
- amPropId[cProps] = PROPID_M_BODY;
- aPropVar[cProps].vt = VT_UI1 | VT_VECTOR;
- aPropVar[cProps].caub.cElems = sizeof(TransferSum);
- aPropVar[cProps].caub.pElems = (unsigned char *)&TransferSum;
- cProps++;
-
- // Create a MSGPROPS structure
- msgprops.cProp = cProps;
- msgprops.aPropID = amPropId;
- msgprops.aPropVar = aPropVar;
- msgprops.aStatus = 0;
-
- }
-
- //--------------------------------------------------------------------------
-
- void CreateQueue (CLSID *pGuidType, WCHAR wsFormat[])
- {
- QUEUEPROPID aqPropId[MAX_VAR];
- WCHAR wsPathName[1000]; //Big path name
- MQPROPVARIANT aPropVar[MAX_VAR];
- DWORD cProps;
- MQQUEUEPROPS qprops;
- DWORD dwSize;
- HRESULT hr;
-
- //---------------------------------------------------------------------
- // Prepare properties to create a queue on local machine
- //---------------------------------------------------------------------
- cProps = 0;
-
- // Set the PathName
- aqPropId[cProps] = PROPID_Q_PATHNAME;
-
- wsprintf(wsPathName, TEXT("%s\\MSMQDemo"), g_wszMachineName);
- aPropVar[cProps].vt = VT_LPWSTR;
- aPropVar[cProps].pwszVal = wsPathName;
- cProps++;
-
- // Set the queue to transactional
- aqPropId[cProps] = PROPID_Q_TRANSACTION;
-
- aPropVar[cProps].vt = VT_UI1;
- aPropVar[cProps].bVal = MQ_TRANSACTIONAL;
- cProps++;
-
- // Set the type of the queue (Will be used to locate queues of this type)
- aqPropId[cProps] = PROPID_Q_TYPE;
-
- aPropVar[cProps].vt = VT_CLSID;
- aPropVar[cProps].puuid = pGuidType;
- cProps++;
-
- // Create a QUEUEPROPS structure
- qprops.cProp = cProps;
- qprops.aPropID = aqPropId;
- qprops.aPropVar = aPropVar;
- qprops.aStatus = 0;
-
- //-----------------------------------------------------------------------
- // Create the queue
- //-----------------------------------------------------------------------
- dwSize = sizeof(WCHAR)*MAX_FORMAT;
- hr = MQCreateQueue(NULL, &qprops, wsFormat, &dwSize);
-
- if(FAILED(hr))
- {
- // API Fails, not because the queue exists
- if(hr != MQ_ERROR_QUEUE_EXISTS)
- Error("Cannot create queue.", hr);
-
- // Queue exist, so get its format name
- // Note: Since queue already exists, this sample assumes
- // that it was created earlier by this program, so we
- // do not check if queue is transactional. If at this point the
- // queue is Not Transactional, the transactions will abort later...
- //
- hr = MQPathNameToFormatName(wsPathName, wsFormat, &dwSize);
-
- if (FAILED(hr))
- Error ("Cannot retrieve format name",hr);
- }
- }
-
- //-------------------------------------------------------------------------------
-
- void LogonToDB(DBCONN *ptr)
- {
- RETCODE retcode = 0;
-
- retcode = SQLAllocConnect(g_hEnv, &(ptr->hdbc) );
-
- if (ProcessRetCode("SQLAllocConnect",ptr,retcode))
- {
- retcode = SQLConnect(ptr->hdbc,
- (UCHAR *)(ptr->pszSrv),
- SQL_NTS,
- (UCHAR *)(ptr->pszUser),
- SQL_NTS,
- (UCHAR *)(ptr->pszPasswd),
- SQL_NTS
- );
-
- ProcessRetCode("SQLConnect",ptr,retcode);
- }
- }
-
- //------------------------------------------------------------------------------
-
- void ExecuteStatement(DBCONN *ptr, char* pszBuf,BOOL ProcessFlag)
- {
- RETCODE retcode = 0;
-
- // Allocate a statement handle for use with SQLExecDirect
- retcode = SQLAllocStmt(ptr->hdbc,&(ptr->hstmt));
-
- if (ProcessFlag)
- ProcessRetCode("SQLAllocStmt",ptr,retcode);
-
- // Execute the passed string as a SQL statement
- retcode = SQLExecDirect (ptr->hstmt,(UCHAR *) pszBuf,SQL_NTS);
-
- if (ProcessFlag)
- ProcessRetCode("SQLExecDirect",ptr,retcode);
-
- // Free the statement handle
- retcode = SQLFreeStmt(ptr->hstmt, SQL_DROP);
- ptr->hstmt = SQL_NULL_HSTMT;
-
- if (ProcessFlag)
- ProcessRetCode("SQLFreeStmt",ptr,retcode);
-
- }
-
- // ---------------------------------------------------------------------------
-
- void DisplayDollars (DBCONN *ptr, char *psAccount)
- {
-
- DWORD DollarsSum; // in SQL database
- SDWORD cbValue; // OUT argument for SQL query
- char sSQLStatement[STR_LEN*2];
- RETCODE retcode;
-
-
-
-
- // Allocate a statement handle for use with SQLExecDirect
- retcode = SQLAllocStmt(ptr->hdbc,&(ptr->hstmt));
-
- ProcessRetCode("SQLAllocStmt",ptr,retcode);
-
-
- // Prepare SQL Statement to issue query
- sprintf (sSQLStatement, "SELECT * FROM %s", psAccount);
-
-
- // Issue SQL query
- retcode = SQLExecDirect (ptr->hstmt,(UCHAR *)sSQLStatement,SQL_NTS);
-
- ProcessRetCode ("SQLExecDirect",ptr,retcode);
-
-
- // Prepare data structure to retrieve query results
- retcode = SQLBindCol(ptr->hstmt,1,SQL_C_ULONG,&DollarsSum,0,&cbValue);
-
- ProcessRetCode ("SQLBindCol",ptr,retcode);
-
-
- // Retrieve query results
- retcode = SQLFetch (ptr->hstmt);
-
- ProcessRetCode ("SQLFetch",ptr,retcode);
-
-
- // Display query results
- printf ("Sum of dollars in %s is %d .\n\n",psAccount,DollarsSum);
-
-
- // Free the statement handle
- retcode = SQLFreeStmt(ptr->hstmt, SQL_DROP);
- ptr->hstmt = SQL_NULL_HSTMT;
-
- ProcessRetCode("SQLFreeStmt",ptr,retcode);
-
- }
-
- // ---------------------------------------------------------------------------
-
- void FreeODBCHandles(DBCONN *ptr)
- {
- SQLDisconnect(ptr->hdbc);
-
- SQLFreeConnect(ptr->hdbc);
-
- ptr->hdbc = SQL_NULL_HDBC;
- ptr->hstmt = SQL_NULL_HSTMT;
- }
-
-
- // ---------------------------------------------------------------------------
-
- BOOL ProcessRetCode(char* pszFuncName,
- DBCONN *ptr,
- RETCODE retcode,
- BOOL fExit)
- {
- BOOL state = TRUE ;
- BOOL fExitP = fExit ;
-
- switch (retcode)
- {
-
- case SQL_SUCCESS:
- fExitP = FALSE ;
- break;
-
- case SQL_SUCCESS_WITH_INFO:
- fExitP = FALSE ;
- break;
-
- case SQL_ERROR:
- printf("%s Failed - see more info\n",pszFuncName);
- DoSQLError(ptr);
- state = FALSE;
- break;
-
- case SQL_INVALID_HANDLE:
- printf("%s Failed - SQL_INVALID_HANDLE\n",pszFuncName);
- state = FALSE;
- break;
-
- case SQL_NO_DATA_FOUND:
- printf("%s Failed - SQL_NO_DATA_FOUND\n",pszFuncName);
- fExitP = FALSE ;
- state = FALSE;
- break;
-
- case SQL_STILL_EXECUTING:
- printf("%s Failed - SQL_STILL_EXECUTING\n",pszFuncName);
- fExitP = FALSE ;
- state = FALSE;
- break;
-
- case SQL_NEED_DATA:
- printf("%s Failed - SQL_NEED_DATA\n",pszFuncName);
- fExitP = FALSE ;
- state = FALSE;
- break;
-
- default:
- printf("%s Failed - unexpected error, retcode = %x\n",pszFuncName,retcode);
- DoSQLError(ptr);
- state = FALSE;
- break;
- }
-
- if (fExitP)
- {
- exit(-1) ;
- }
- return state ;
- }
-
- // ---------------------------------------------------------------------------
-
- void DoSQLError(DBCONN *ptr)
- {
-
- const INT MSG_BUF_SIZE = 300;
- UCHAR szSqlState[MSG_BUF_SIZE];
- UCHAR szErrorMsg[MSG_BUF_SIZE];
-
- SQLINTEGER fNativeError = 0;
- SWORD cbErrorMsg = MSG_BUF_SIZE;
- RETCODE retcode;
-
- retcode = SQLError(g_hEnv,
- ptr ? ptr->hdbc : 0,
- ptr ? ptr->hstmt :0,
- szSqlState,
- &fNativeError,
- szErrorMsg,
- MSG_BUF_SIZE,
- &cbErrorMsg
- );
-
- if (retcode != SQL_NO_DATA_FOUND && retcode != SQL_ERROR)
- {
- if (fNativeError != 0x1645) // ignore change database to master context message
- {
- printf("SQLError info:\n");
- printf("SqlState: %s, fNativeError: %x\n",szSqlState,fNativeError);
- printf("Error Message: %s\n\n",szErrorMsg);
- }
- }
- else
- {
- printf("SQLError() failed: %x, NO_DATA_FOUND OR SQL_ERROR\n",retcode);
- }
-
- }
- // ---------------------------------------------------------------------------
-
-