Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

835 lines
21 KiB

  1. /******************************************************************************\
  2. * This is a part of the Microsoft Source Code Samples.
  3. * Copyright (C) 1999 Microsoft Corporation.
  4. * All rights reserved.
  5. * This source code is only intended as a supplement to
  6. * Microsoft Development Tools and/or WinHelp documentation.
  7. * See these sources for detailed information regarding the
  8. * Microsoft samples programs.
  9. \******************************************************************************/
  10. //
  11. // Includes
  12. //
  13. #include <stdio.h>
  14. #include <windows.h>
  15. //
  16. // Unique include file for ActiveX MSMQ apps
  17. //
  18. #include <mqoai.h>
  19. //
  20. // Various defines
  21. //
  22. #define MAX_VAR 20
  23. #define MAX_BUFFER 500
  24. //
  25. // GUID created with the tool "GUIDGEN"
  26. //
  27. static WCHAR strGuidMQTestType[] =
  28. L"{c30e0960-a2c0-11cf-9785-00608cb3e80c}";
  29. //
  30. // Prototypes
  31. //
  32. void PrintError(char *s, HRESULT hr);
  33. HRESULT Syntax();
  34. char mbsMachineName[MAX_COMPUTERNAME_LENGTH + 1];
  35. // Some useful macros
  36. #define RELEASE(punk) if (punk) { (punk)->Release(); (punk) = NULL; }
  37. #define ADDREF(punk) ((punk) ? (punk)->AddRef() : 0)
  38. #define PRINTERROR(s, hr) { PrintError(s, hr); goto Cleanup; }
  39. //-----------------------------------------------------
  40. //
  41. // Check if local computer is DS enabled or DS disabled
  42. //
  43. //-----------------------------------------------------
  44. short DetectDsConnection(void)
  45. {
  46. IMSMQApplication2 *pqapp = NULL;
  47. short fDsConnection;
  48. HRESULT hresult;
  49. hresult = CoCreateInstance(
  50. CLSID_MSMQApplication,
  51. NULL, // punkOuter
  52. CLSCTX_SERVER,
  53. IID_IMSMQApplication2,
  54. (LPVOID *)&pqapp);
  55. if (FAILED(hresult))
  56. PRINTERROR("Cannot create application", hresult);
  57. pqapp->get_IsDsEnabled(&fDsConnection);
  58. Cleanup:
  59. RELEASE(pqapp);
  60. return fDsConnection;
  61. }
  62. //-----------------------------------------------------
  63. //
  64. // Allow a DS enabled client connect with a
  65. // DS disabled one.
  66. //
  67. //-----------------------------------------------------
  68. bool SetConnectionMode(void)
  69. {
  70. char cDirectMode;
  71. //
  72. // In case the local computer is DS enabled,
  73. // we have two cases:
  74. // 1. Other side is a DS enabled computer.
  75. // 2. Other side is a DS disabled computer.
  76. //
  77. if(DetectDsConnection() != 0)
  78. {
  79. printf("Do you wish to connect with a DS disabled computer (y or n) ? ");
  80. scanf("%c", &cDirectMode);
  81. switch(tolower(cDirectMode))
  82. {
  83. case 'y':
  84. return true;
  85. case 'n':
  86. return false;
  87. default:
  88. printf("Bye.\n");
  89. exit(1);
  90. }
  91. }
  92. return true; // Local computer is DS disabled
  93. }
  94. //--------------------------------------------------------
  95. //
  96. // Receiver Mode
  97. // -------------
  98. // The receiver side does the following:
  99. // 1. Creates a queue on its own computer'
  100. // of type "guidMQTestType".
  101. // The queue is either public or private, depending
  102. // on the connection we wish to establish
  103. // 2. Opens the queue
  104. // 3. In a Loop
  105. // Receives messages
  106. // Prints message body and message label
  107. // 4. Cleanup handles
  108. // 5. Deletes the queue from the directory service
  109. //
  110. //--------------------------------------------------------
  111. HRESULT Receiver(bool fDirectMode)
  112. {
  113. IMSMQMessage *pmessageReceive = NULL;
  114. IMSMQQueue *pqReceive = NULL;
  115. IMSMQQueueInfo *pqinfo = NULL;
  116. BSTR bstrPathName = NULL;
  117. BSTR bstrServiceType = NULL;
  118. BSTR bstrLabel = NULL;
  119. BSTR bstrMsgLabel = NULL;
  120. VARIANT varIsTransactional, varIsWorldReadable, varBody, varBody2, varWantDestQueue, varWantBody, varReceiveTimeout;
  121. WCHAR wcsPathName[1000];
  122. BOOL fQuit = FALSE;
  123. HRESULT hresult = NOERROR;
  124. printf("\nReceiver Mode on Machine: %s\n\n", mbsMachineName);
  125. //
  126. // Create MSMQQueueInfo object
  127. //
  128. hresult = CoCreateInstance(
  129. CLSID_MSMQQueueInfo,
  130. NULL, // punkOuter
  131. CLSCTX_SERVER,
  132. IID_IMSMQQueueInfo,
  133. (LPVOID *)&pqinfo);
  134. if (FAILED(hresult)) {
  135. PRINTERROR("Cannot create queue", hresult);
  136. }
  137. //
  138. // Prepare properties to create a queue on local machine
  139. //
  140. // Set the PathName
  141. if(fDirectMode) // Private queue pathname
  142. {
  143. swprintf(wcsPathName, L"%S\\private$\\MSMQTest", mbsMachineName);
  144. }
  145. else // Public queue pathname
  146. {
  147. swprintf(wcsPathName, L"%S\\MSMQTest", mbsMachineName);
  148. }
  149. bstrPathName = SysAllocString(wcsPathName);
  150. if (bstrPathName == NULL) {
  151. PRINTERROR("OOM: pathname", E_OUTOFMEMORY);
  152. }
  153. pqinfo->put_PathName(bstrPathName);
  154. //
  155. // Set the type of the queue
  156. // (Will be used to locate all the queues of this type)
  157. //
  158. bstrServiceType = SysAllocString(strGuidMQTestType);
  159. if (bstrServiceType == NULL) {
  160. PRINTERROR("OOM: ServiceType", E_OUTOFMEMORY);
  161. }
  162. pqinfo->put_ServiceTypeGuid(bstrServiceType);
  163. //
  164. // Put a description to the queue
  165. // (Useful for administration through the MSMQ admin tools)
  166. //
  167. bstrLabel =
  168. SysAllocString(L"Sample ActiveX application of MSMQ SDK");
  169. if (bstrLabel == NULL) {
  170. PRINTERROR("OOM: label ", E_OUTOFMEMORY);
  171. }
  172. pqinfo->put_Label(bstrLabel);
  173. //
  174. // specify if transactional
  175. //
  176. VariantInit(&varIsTransactional);
  177. varIsTransactional.vt = VT_BOOL;
  178. varIsTransactional.boolVal = MQ_TRANSACTIONAL_NONE;
  179. VariantInit(&varIsWorldReadable);
  180. varIsWorldReadable.vt = VT_BOOL;
  181. varIsWorldReadable.boolVal = FALSE;
  182. //
  183. // create the queue
  184. //
  185. hresult = pqinfo->Create(&varIsTransactional, &varIsWorldReadable);
  186. if (FAILED(hresult)) {
  187. //
  188. // API Fails, not because the queue exists
  189. //
  190. if (hresult != MQ_ERROR_QUEUE_EXISTS)
  191. PRINTERROR("Cannot create queue", hresult);
  192. }
  193. //
  194. // Open the queue for receive access
  195. //
  196. hresult = pqinfo->Open(MQ_RECEIVE_ACCESS,
  197. MQ_DENY_NONE,
  198. &pqReceive);
  199. //
  200. // Little bit tricky. MQCreateQueue succeeded but, in case
  201. // it's a public queue, it does not mean that MQOpenQueue
  202. // will, because of replication delay. The queue is registered
  203. // in MQIS, but it might take a replication interval
  204. // until the replica reaches the server I am connected to.
  205. // To overcome this, open the queue in a loop.
  206. //
  207. // (in this specific case, this can happen only if this
  208. // program is run on a Backup Server Controller - BSC, or on
  209. // a client connected to a BSC)
  210. // To be totally on the safe side, we should have put some code
  211. // to exit the loop after a few retries, but hey, this is just a sample.
  212. //
  213. while (hresult == MQ_ERROR_QUEUE_NOT_FOUND) {
  214. printf(".");
  215. // Wait a bit
  216. Sleep(500);
  217. // And retry
  218. hresult = pqinfo->Open(MQ_RECEIVE_ACCESS,
  219. MQ_DENY_NONE,
  220. &pqReceive);
  221. }
  222. if (FAILED(hresult)) {
  223. PRINTERROR("Cannot open queue", hresult);
  224. }
  225. //
  226. // Main receiver loop
  227. //
  228. printf("\nWaiting for messages...\n");
  229. while (!fQuit) {
  230. //
  231. // Receive the message
  232. //
  233. VariantInit(&varWantDestQueue);
  234. VariantInit(&varWantBody);
  235. VariantInit(&varReceiveTimeout);
  236. varWantDestQueue.vt = VT_BOOL;
  237. varWantDestQueue.boolVal = TRUE; // yes we want the dest queue
  238. varWantBody.vt = VT_BOOL;
  239. varWantBody.boolVal = TRUE; // yes we want the msg body
  240. varReceiveTimeout.vt = VT_I4;
  241. varReceiveTimeout.lVal = INFINITE; // infinite timeout
  242. hresult = pqReceive->Receive(
  243. NULL,
  244. &varWantDestQueue,
  245. &varWantBody,
  246. &varReceiveTimeout,
  247. &pmessageReceive);
  248. if (FAILED(hresult)) {
  249. PRINTERROR("Receive message", hresult);
  250. }
  251. //
  252. // Display the received message
  253. //
  254. pmessageReceive->get_Label(&bstrMsgLabel);
  255. VariantInit(&varBody);
  256. VariantInit(&varBody2);
  257. hresult = pmessageReceive->get_Body(&varBody);
  258. if (FAILED(hresult)) {
  259. PRINTERROR("can't get body", hresult);
  260. }
  261. hresult = VariantChangeType(&varBody2,
  262. &varBody,
  263. 0,
  264. VT_BSTR);
  265. if (FAILED(hresult)) {
  266. PRINTERROR("can't convert message to string.", hresult);
  267. }
  268. printf("%S : %s\n", bstrMsgLabel, V_BSTR(&varBody2));
  269. //
  270. // Check for end of app
  271. //
  272. if (stricmp((char *)V_BSTR(&varBody2), "quit") == 0) {
  273. fQuit = TRUE;
  274. }
  275. VariantClear(&varBody);
  276. VariantClear(&varBody2);
  277. //
  278. // release the current message
  279. //
  280. RELEASE(pmessageReceive);
  281. } /* while (!fQuit) */
  282. //
  283. // Cleanup - Close handle to the queue
  284. //
  285. pqReceive->Close();
  286. if (FAILED(hresult)) {
  287. PRINTERROR("Cannot close queue", hresult);
  288. }
  289. //
  290. // Finish - Let's delete the queue from the directory service
  291. // (We don't need to do it. In case of a public queue, leaving
  292. // it in the DS enables sender applications to send messages
  293. // even if the receiver is not available.)
  294. //
  295. hresult = pqinfo->Delete();
  296. if (FAILED(hresult)) {
  297. PRINTERROR("Cannot delete queue", hresult);
  298. }
  299. // fall through...
  300. Cleanup:
  301. SysFreeString(bstrPathName);
  302. SysFreeString(bstrMsgLabel);
  303. SysFreeString(bstrServiceType);
  304. SysFreeString(bstrLabel);
  305. RELEASE(pmessageReceive);
  306. RELEASE(pqReceive);
  307. RELEASE(pqinfo);
  308. return hresult;
  309. }
  310. //-----------------------------------------------------
  311. //
  312. // Sender Mode
  313. // -----------
  314. // The sender side does the following:
  315. //
  316. // If we work in STANDARD mode:
  317. // 1. Locates all queues of type "guidMQTestType"
  318. // 2. Opens handles to all the queues
  319. // 3. In a loop
  320. // Sends messages to all those queues
  321. // 4. Cleans up handles
  322. //
  323. // If we work in DIRECT mode:
  324. // 1. Opens a handle to a private queue labeled
  325. // "MSMQTest" on the computer specified
  326. // 2. Sends messages to that queue
  327. // 3. Cleans up handles
  328. //-----------------------------------------------------
  329. //-----------------------------------------------------
  330. //
  331. // Sender in STANDARD mode
  332. //
  333. //-----------------------------------------------------
  334. HRESULT StandardSender()
  335. {
  336. IMSMQQuery *pquery = NULL;
  337. IMSMQQueueInfo *rgpqinfo[MAX_VAR];
  338. IMSMQQueue *rgpqSend[MAX_VAR];
  339. IMSMQQueueInfo *pqinfo = NULL;
  340. IMSMQQueueInfos *pqinfos = NULL;
  341. IMSMQMessage *pmessage = NULL;
  342. char szBuffer[MAX_BUFFER];
  343. WCHAR wcsMsgLabel[MQ_MAX_MSG_LABEL_LEN];
  344. BSTR bstrServiceType = NULL;
  345. BSTR bstrLabel = NULL;
  346. BSTR bstrBody = NULL;
  347. VARIANT varBody;
  348. DWORD i;
  349. DWORD cQueue = 0;
  350. HRESULT hresult = NOERROR;
  351. printf("\nSender Mode on Machine: %s\n\n", mbsMachineName);
  352. //
  353. // create query object for lookup
  354. //
  355. hresult = CoCreateInstance(
  356. CLSID_MSMQQuery,
  357. NULL, // punkOuter
  358. CLSCTX_SERVER,
  359. IID_IMSMQQuery,
  360. (LPVOID *)&pquery);
  361. if (FAILED(hresult)) {
  362. PRINTERROR("Cannot create query", hresult);
  363. }
  364. //
  365. // Prepare parameters to locate a queue: all queues that
  366. // match test guid type
  367. //
  368. VARIANT varGuidQueue;
  369. VARIANT varStrLabel;
  370. VARIANT varGuidServiceType;
  371. VARIANT varRelServiceType;
  372. VARIANT varRelLabel;
  373. VARIANT varCreateTime;
  374. VARIANT varModifyTime;
  375. VARIANT varRelCreateTime;
  376. VARIANT varRelModifyTime;
  377. VariantInit(&varGuidQueue);
  378. VariantInit(&varStrLabel);
  379. VariantInit(&varGuidServiceType);
  380. VariantInit(&varRelServiceType);
  381. VariantInit(&varRelLabel);
  382. VariantInit(&varCreateTime);
  383. VariantInit(&varModifyTime);
  384. VariantInit(&varRelCreateTime);
  385. VariantInit(&varRelModifyTime);
  386. //
  387. // We only want to specify service type so we set
  388. // the other variant params to VT_ERROR to simulate
  389. // "missing", i.e. optional, params.
  390. //
  391. V_VT(&varGuidQueue) = VT_ERROR;
  392. V_VT(&varStrLabel) = VT_ERROR;
  393. V_VT(&varRelServiceType) = VT_ERROR;
  394. V_VT(&varRelLabel) = VT_ERROR;
  395. V_VT(&varCreateTime) = VT_ERROR;
  396. V_VT(&varModifyTime) = VT_ERROR;
  397. V_VT(&varRelCreateTime) = VT_ERROR;
  398. V_VT(&varRelModifyTime) = VT_ERROR;
  399. bstrServiceType = SysAllocString(strGuidMQTestType);
  400. if (bstrServiceType == NULL) {
  401. PRINTERROR("OOM: Service Type", E_OUTOFMEMORY);
  402. }
  403. V_VT(&varGuidServiceType) = VT_BSTR;
  404. V_BSTR(&varGuidServiceType) = bstrServiceType;
  405. hresult = pquery->LookupQueue(&varGuidQueue,
  406. &varGuidServiceType,
  407. &varStrLabel,
  408. &varCreateTime,
  409. &varModifyTime,
  410. &varRelServiceType,
  411. &varRelLabel,
  412. &varRelCreateTime,
  413. &varRelModifyTime,
  414. &pqinfos);
  415. if (FAILED(hresult)) {
  416. PRINTERROR("LookupQueue failed", hresult);
  417. }
  418. //
  419. // reset the queue collection
  420. //
  421. hresult = pqinfos->Reset();
  422. if (FAILED(hresult)) {
  423. PRINTERROR("Reset failed", hresult);
  424. }
  425. //
  426. // Open each of the queues found
  427. //
  428. i = 0;
  429. hresult = pqinfos->Next(&rgpqinfo[i]);
  430. if (FAILED(hresult)) {
  431. PRINTERROR("Next failed", hresult);
  432. }
  433. pqinfo = rgpqinfo[i];
  434. while (pqinfo) {
  435. //
  436. // Open the queue for send access
  437. //
  438. hresult = pqinfo->Open(
  439. MQ_SEND_ACCESS,
  440. MQ_DENY_NONE,
  441. &rgpqSend[i]);
  442. if (FAILED(hresult)) {
  443. PRINTERROR("Open failed", hresult);
  444. }
  445. i++;
  446. hresult = pqinfos->Next(&rgpqinfo[i]);
  447. if (FAILED(hresult)) {
  448. PRINTERROR("Next failed", hresult);
  449. }
  450. pqinfo = rgpqinfo[i];
  451. }
  452. cQueue = i;
  453. if (cQueue == 0) {
  454. //
  455. // Could Not find any queue, so exit
  456. //
  457. PRINTERROR("No queue registered", hresult = E_INVALIDARG);
  458. }
  459. printf("\t%d queue(s) found.\n", cQueue);
  460. printf("\nEnter \"quit\" to exit\n");
  461. //
  462. // Build the message label property
  463. //
  464. swprintf(wcsMsgLabel, L"Message from %S", mbsMachineName);
  465. bstrLabel = SysAllocString(wcsMsgLabel);
  466. if (bstrLabel == NULL)
  467. PRINTERROR("OOM: label", E_OUTOFMEMORY);
  468. fflush(stdin);
  469. //
  470. // Main sender loop
  471. //
  472. while (1) {
  473. //
  474. // Get a string from the console
  475. //
  476. printf("Enter a string: ");
  477. if (gets(szBuffer) == NULL)
  478. break;
  479. //
  480. // create a message object
  481. //
  482. hresult = CoCreateInstance(
  483. CLSID_MSMQMessage,
  484. NULL, // punkOuter
  485. CLSCTX_SERVER,
  486. IID_IMSMQMessage,
  487. (LPVOID *)&pmessage);
  488. //
  489. // Send the message to all the queues
  490. //
  491. for (i = 0; i < cQueue; i++)
  492. {
  493. hresult = pmessage->put_Label(bstrLabel);
  494. //
  495. // This isn't a "true" unicode string of course...
  496. //
  497. bstrBody = SysAllocStringByteLen(szBuffer, strlen(szBuffer)+1);
  498. if (bstrBody == NULL) {
  499. PRINTERROR("OOM: body", E_OUTOFMEMORY);
  500. }
  501. VariantInit(&varBody);
  502. V_VT(&varBody) = VT_BSTR;
  503. V_BSTR(&varBody) = bstrBody;
  504. hresult = pmessage->put_Body(varBody);
  505. if (FAILED(hresult)) {
  506. PRINTERROR("put_body failed", hresult);
  507. }
  508. hresult = pmessage->Send(rgpqSend[i], NULL);
  509. if (FAILED(hresult)) {
  510. PRINTERROR("Send failed", hresult);
  511. }
  512. VariantClear(&varBody);
  513. bstrBody = NULL;
  514. }
  515. RELEASE(pmessage);
  516. //
  517. // Check for end of app
  518. //
  519. if (stricmp(szBuffer, "quit") == 0)
  520. break;
  521. } /* while (1) */
  522. Cleanup:
  523. //
  524. // Close and release all the queues
  525. //
  526. for (i = 0; i < cQueue; i++) {
  527. rgpqSend[i]->Close();
  528. rgpqSend[i]->Release();
  529. rgpqinfo[i]->Release();
  530. }
  531. RELEASE(pqinfos);
  532. RELEASE(pquery);
  533. RELEASE(pmessage);
  534. SysFreeString(bstrLabel);
  535. SysFreeString(bstrBody);
  536. SysFreeString(bstrServiceType);
  537. return hresult;
  538. }
  539. //-----------------------------------------------------
  540. //
  541. // Sender in DIRECT mode
  542. //
  543. //-----------------------------------------------------
  544. HRESULT DirectSender(void)
  545. {
  546. IMSMQQueue *rgpqSend;
  547. IMSMQQueueInfo *pqinfo = NULL;
  548. IMSMQMessage *pmessage = NULL;
  549. char szBuffer[MAX_BUFFER];
  550. WCHAR wcsMsgLabel[MQ_MAX_MSG_LABEL_LEN];
  551. WCHAR wcsFormat[MAX_BUFFER];
  552. WCHAR wcsReceiverComputer[MAX_BUFFER];
  553. BSTR bstrFormat = NULL;
  554. BSTR bstrServiceType = NULL;
  555. BSTR bstrLabel = NULL;
  556. BSTR bstrBody = NULL;
  557. VARIANT varBody;
  558. DWORD cQueue = 0;
  559. HRESULT hresult = NOERROR;
  560. //
  561. // Get the receiver computer name
  562. //
  563. printf("\nEnter receiver computer name: ");
  564. wscanf(L"%s", wcsReceiverComputer);
  565. if(wcsReceiverComputer[0] == 0)
  566. {
  567. printf("You have entered an incorrect parameter. Exiting...\n");
  568. return E_INVALIDARG;
  569. }
  570. hresult = CoCreateInstance(
  571. CLSID_MSMQQueueInfo,
  572. NULL, // punkOuter
  573. CLSCTX_SERVER,
  574. IID_IMSMQQueueInfo,
  575. (LPVOID *)&pqinfo);
  576. if (FAILED(hresult))
  577. PRINTERROR("Cannot open queue", hresult);
  578. swprintf(wcsFormat, L"DIRECT=OS:%s\\private$\\MSMQTest", wcsReceiverComputer);
  579. bstrFormat = SysAllocString(wcsFormat);
  580. hresult = pqinfo->put_FormatName(bstrFormat);
  581. if (FAILED(hresult))
  582. PRINTERROR("Open failed", hresult);
  583. //
  584. // Open the queue for send access
  585. //
  586. hresult = pqinfo->Open(
  587. MQ_SEND_ACCESS,
  588. MQ_DENY_NONE,
  589. &rgpqSend);
  590. if (FAILED(hresult))
  591. PRINTERROR("Open failed", hresult);
  592. printf("\nSender Mode on Machine: %s\n\n", mbsMachineName);
  593. printf("\nEnter \"quit\" to exit\n");
  594. //
  595. // Build the message label property
  596. //
  597. swprintf(wcsMsgLabel, L"Message from %S", mbsMachineName);
  598. bstrLabel = SysAllocString(wcsMsgLabel);
  599. if (bstrLabel == NULL)
  600. PRINTERROR("OOM: label", E_OUTOFMEMORY);
  601. fflush(stdin);
  602. //
  603. // Main sender loop
  604. //
  605. while (1)
  606. {
  607. //
  608. // Get a string from the console
  609. //
  610. printf("Enter a string: ");
  611. if (gets(szBuffer) == NULL)
  612. break;
  613. //
  614. // create a message object
  615. //
  616. hresult = CoCreateInstance(
  617. CLSID_MSMQMessage,
  618. NULL, // punkOuter
  619. CLSCTX_SERVER,
  620. IID_IMSMQMessage,
  621. (LPVOID *)&pmessage);
  622. //
  623. // Send the message
  624. //
  625. hresult = pmessage->put_Label(bstrLabel);
  626. bstrBody = SysAllocStringByteLen(szBuffer, strlen(szBuffer)+1);
  627. if (bstrBody == NULL)
  628. PRINTERROR("OOM: body", E_OUTOFMEMORY);
  629. VariantInit(&varBody);
  630. V_VT(&varBody) = VT_BSTR;
  631. V_BSTR(&varBody) = bstrBody;
  632. hresult = pmessage->put_Body(varBody);
  633. if (FAILED(hresult))
  634. PRINTERROR("put_body failed", hresult);
  635. hresult = pmessage->Send(rgpqSend, NULL);
  636. if (FAILED(hresult))
  637. PRINTERROR("Send failed", hresult);
  638. VariantClear(&varBody);
  639. bstrBody = NULL;
  640. RELEASE(pmessage);
  641. //
  642. // Check for end of app
  643. //
  644. if (stricmp(szBuffer, "quit") == 0)
  645. break;
  646. } /* while (1) */
  647. Cleanup:
  648. rgpqSend->Close();
  649. rgpqSend->Release();
  650. RELEASE(pqinfo);
  651. RELEASE(pmessage);
  652. SysFreeString(bstrFormat);
  653. SysFreeString(bstrLabel);
  654. SysFreeString(bstrBody);
  655. SysFreeString(bstrServiceType);
  656. return hresult;
  657. }
  658. //------------------------------------------------------
  659. //
  660. // Sender function
  661. //
  662. //------------------------------------------------------
  663. HRESULT Sender(int fDirectMode)
  664. {
  665. if(fDirectMode != 0)
  666. return DirectSender();
  667. else
  668. return StandardSender();
  669. }
  670. //-----------------------------------------------------
  671. //
  672. // MAIN
  673. //
  674. //-----------------------------------------------------
  675. int main(int argc, char * * argv)
  676. {
  677. DWORD dwNumChars;
  678. HRESULT hresult = NOERROR;
  679. bool fDirectMode;
  680. if (argc != 2)
  681. return Syntax();
  682. hresult = OleInitialize(NULL);
  683. if (FAILED(hresult))
  684. PRINTERROR("Cannot init OLE", hresult);
  685. //
  686. // Retrieve machine name
  687. //
  688. dwNumChars = MAX_COMPUTERNAME_LENGTH + 1;
  689. GetComputerNameA(mbsMachineName, &dwNumChars);
  690. //
  691. // Detect DS connection and working mode
  692. //
  693. fDirectMode = SetConnectionMode();
  694. if (strcmp(argv[1], "-s") == 0)
  695. hresult = Sender(fDirectMode);
  696. else if (strcmp(argv[1], "-r") == 0)
  697. hresult = Receiver(fDirectMode);
  698. else
  699. hresult = Syntax();
  700. printf("\nOK\n");
  701. // fall through...
  702. Cleanup:
  703. return (int)hresult;
  704. }
  705. void PrintError(char *s, HRESULT hr)
  706. {
  707. printf("Cleanup: %s (0x%X)\n", s, hr);
  708. }
  709. HRESULT Syntax()
  710. {
  711. printf("\n");
  712. printf("Syntax: mqtestoa -s | -r\n");
  713. printf("\t-s: Sender\n");
  714. printf("\t-r: Receiver\n");
  715. return E_INVALIDARG;
  716. }