Leaked source code of windows server 2003
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.

784 lines
21 KiB

  1. /*++
  2. Copyright (c) 1992-2001 Microsoft Corporation
  3. Module Name:
  4. mqrcvr.cpp
  5. Abstract:
  6. Receives file names from server and launches debugger
  7. --*/
  8. //
  9. // Includes
  10. //
  11. #ifndef MQEXTDLL
  12. #include <stdio.h>
  13. #include <windows.h>
  14. #include <objbase.h>
  15. #define dprintf printf
  16. #else
  17. #include "mqext.h"
  18. #endif
  19. //
  20. // Unique include file for ActiveX MSMQ apps
  21. //
  22. #include <mqoai.h>
  23. #include <mq.h>
  24. #include <strsafe.h>
  25. //
  26. // Various defines
  27. //
  28. #define MAX_VAR 20
  29. #define MAX_BUFFER 500
  30. //
  31. // GUID created with the tool "GUIDGEN"
  32. //
  33. static WCHAR strGuidMQTestType[] =
  34. L"{c30e0960-a2c0-11cf-9785-00608cb3e80c}";
  35. //
  36. // Prototypes
  37. //
  38. void PrintError(char *s, HRESULT hr);
  39. HRESULT Syntax();
  40. char g_DebuggerName[MAX_PATH];
  41. char g_SymCache[MAX_PATH];
  42. char g_ServerMachine[MAX_COMPUTERNAME_LENGTH*4 + 1];
  43. char g_FormatName[MAX_PATH] = {0};
  44. char g_QueueName[100];
  45. CHAR g_DumpPath[MAX_PATH + 1];
  46. BOOL g_Retriage = FALSE;
  47. BOOL g_NoCustomer = FALSE;
  48. BOOL g_SendMail = FALSE;
  49. ULONG g_MaxMemUsage = 50;
  50. ULONG g_PauseForNext = 1000;
  51. BOOL g_CreateQ = 0;
  52. BOOL g_bSend = FALSE;
  53. // Some useful macros
  54. #define RELEASE(punk) if (punk) { (punk)->Release(); (punk) = NULL; }
  55. #define ADDREF(punk) ((punk) ? (punk)->AddRef() : 0)
  56. #define PRINTERROR(s, hr) { PrintError(s, hr); goto Cleanup; }
  57. BOOL
  58. GetArgs(int Argc, CHAR ** Argv)
  59. {
  60. int i = 1;
  61. g_ServerMachine[0] = 0;
  62. g_QueueName[0] = 0;
  63. StringCchCopy(g_DebuggerName, sizeof(g_DebuggerName), "c:\\Debuggers\\ocakd.exe");
  64. StringCchCopy(g_SymCache, sizeof(g_SymCache), "c:\\symcache");
  65. g_bSend = FALSE;
  66. while (i<Argc)
  67. {
  68. if (!strcmp(Argv[i], "-create"))
  69. {
  70. ++i;
  71. g_CreateQ = TRUE;
  72. }
  73. else if (!strcmp(Argv[i],"-d"))
  74. {
  75. // Get sender format name
  76. ++i;
  77. if ((i < Argc) &&
  78. (strlen(Argv[i]) < MAX_PATH))
  79. {
  80. StringCchCopy(g_DebuggerName, sizeof(g_DebuggerName), Argv[i]);
  81. ++i;
  82. }
  83. }
  84. else if (!strcmp(Argv[i],"-f"))
  85. {
  86. // Get sender format name
  87. ++i;
  88. if ((i < Argc) &&
  89. (strlen(Argv[i]) < MAX_PATH))
  90. {
  91. StringCchCopy(g_FormatName, sizeof(g_FormatName), Argv[i]);
  92. ++i;
  93. }
  94. }
  95. else if (!strcmp(Argv[i], "-m"))
  96. {
  97. ++i;
  98. // get memory usage value
  99. if (i<Argc)
  100. {
  101. g_MaxMemUsage = atoi(Argv[i]);
  102. ++i;
  103. }
  104. }
  105. else if (!strcmp(Argv[i], "-mail"))
  106. {
  107. ++i;
  108. g_SendMail = TRUE;
  109. }
  110. else if (!strcmp(Argv[i], "-nocust"))
  111. {
  112. ++i;
  113. g_NoCustomer = TRUE;
  114. }
  115. else if (!strcmp(Argv[i], "-p") ||
  116. !strcmp(Argv[i], "-pause"))
  117. {
  118. ++i;
  119. // get memory usage value
  120. if (i<Argc)
  121. {
  122. g_PauseForNext = atoi(Argv[i]);
  123. ++i;
  124. }
  125. }
  126. else if (!strcmp(Argv[i], "-q"))
  127. {
  128. ++i;
  129. // Get Queue name
  130. if ((i < Argc) &&
  131. (strlen(Argv[i]) < sizeof(g_QueueName)))
  132. {
  133. StringCchCopy(g_QueueName, sizeof(g_QueueName), Argv[i]);
  134. ++i;
  135. }
  136. }
  137. else if (!strcmp(Argv[i],"-retriage"))
  138. {
  139. // Get sender server machine name
  140. ++i;
  141. g_Retriage = TRUE;
  142. }
  143. else if (!strcmp(Argv[i],"-s"))
  144. {
  145. // Get sender server machine name
  146. ++i;
  147. if ((i < Argc) &&
  148. (strlen(Argv[i]) < MAX_COMPUTERNAME_LENGTH*4))
  149. {
  150. StringCchCopy(g_ServerMachine, sizeof(g_ServerMachine), Argv[i]);
  151. ++i;
  152. }
  153. }
  154. else if (!strcmp(Argv[i],"-send"))
  155. {
  156. // Get sender server machine name
  157. ++i;
  158. g_bSend = TRUE;
  159. }
  160. else if (!strcmp(Argv[i],"-y"))
  161. {
  162. ++i;
  163. if ((i < Argc) &&
  164. (strlen(Argv[i]) < MAX_PATH))
  165. {
  166. StringCchCopy(g_SymCache, sizeof(g_SymCache), Argv[i]);
  167. ++i;
  168. }
  169. }
  170. else
  171. {
  172. printf("Unkonwn argument %s\n", Argv[i]);
  173. return FALSE;
  174. }
  175. }
  176. return (g_ServerMachine[0] && g_QueueName[0]) || g_FormatName[0] ;
  177. }
  178. /*
  179. LaunchDebugger - Launches a debugger process
  180. Input : g_DumpPath has the dump file name to run debugger on
  181. fWait - Wait for process to finish
  182. Return: Succesful creation of process or the process exit code
  183. */
  184. HRESULT
  185. LaunchDebugger(BOOL fWait)
  186. {
  187. STARTUPINFO StartupInfo;
  188. PROCESS_INFORMATION ProcessInfo;
  189. ULONG ExitCode;
  190. TCHAR CommandLine[2048];
  191. HRESULT hr;
  192. ZeroMemory(&StartupInfo,sizeof(STARTUPINFO));
  193. StartupInfo.cb = sizeof(STARTUPINFO);
  194. StringCbPrintf(CommandLine, sizeof(CommandLine),
  195. "%s -i srv*%s*\\\\symbols\\symbols -y srv*%s*\\\\symbols\\symbols -z %s "
  196. "-c \"!dbaddcrash %s %s %s -p %s;q\"",
  197. g_DebuggerName,
  198. g_SymCache,
  199. g_SymCache,
  200. g_DumpPath,
  201. g_Retriage ? ("-retriage") : (""),
  202. g_SendMail ? ("-mail") : (""),
  203. g_NoCustomer ? ("-nocust") : (""),
  204. g_DumpPath);
  205. dprintf("Executing: %s\n", CommandLine);
  206. if (!CreateProcess(g_DebuggerName,
  207. CommandLine,
  208. NULL,
  209. NULL,
  210. FALSE,
  211. CREATE_NEW_CONSOLE,
  212. // CREATE_NO_WINDOW,
  213. NULL,
  214. NULL,
  215. &StartupInfo,
  216. &ProcessInfo))
  217. {
  218. hr = GetLastError();
  219. dprintf("Failed to launch debugger for %s, error %lx\n",
  220. g_DumpPath, hr);
  221. return hr;
  222. }
  223. else if (fWait)
  224. {
  225. // wait for process to finish
  226. WaitForSingleObject(ProcessInfo.hProcess,INFINITE);
  227. GetExitCodeProcess( ProcessInfo.hProcess, (LPDWORD) &hr);
  228. dprintf ("Debugger Exited with Exit code: %lx",hr);
  229. }
  230. else
  231. {
  232. hr = S_OK;
  233. }
  234. CloseHandle( ProcessInfo.hThread );
  235. CloseHandle( ProcessInfo.hProcess);
  236. return hr;
  237. }
  238. /**************************************************************************************************************
  239. //
  240. // This creates and opens up a MSMQ to send messages. Queue is created / opened on g_ServerMachine and Queue name
  241. // is taken from g_QueueName.
  242. //
  243. // pwszQueueFormatName - Format name identyfying the queue to be opened
  244. //
  245. // pwszQueuePathName - Path name identyfying the queue to be opened, this isn't used when
  246. // pwszQueueFormatName is present
  247. //
  248. // bSendQueue - Specifies whether Queue has send or receive access
  249. //
  250. // On success the queue handle is returned in pStartedQ. bCreated is set depending on whether the Queue was created
  251. // Caller must CloseSendQ after its done sending messages.
  252. //
  253. ***************************************************************************************************************/
  254. HRESULT
  255. StartMessageQ(
  256. PWSTR pwszQueueFormatName,
  257. PWSTR pwszQueuePathName,
  258. BOOL bSendQueue,
  259. QUEUEHANDLE* pStartedQ,
  260. BOOL* bCreated)
  261. {
  262. HRESULT Hr = S_OK;
  263. QUEUEHANDLE hQueue;
  264. DWORD i;
  265. if (!pwszQueueFormatName && !pwszQueuePathName )
  266. {
  267. Hr = E_INVALIDARG;
  268. PRINTERROR("No queue connection string specified", Hr);
  269. }
  270. if (g_CreateQ)
  271. {
  272. MQQUEUEPROPS QueueProps;
  273. QUEUEPROPID PropIDs[2];
  274. MQPROPVARIANT PropVariants[2];
  275. HRESULT hrProps[2];
  276. ULONG FormatLength = 0;
  277. i = 0;
  278. if (pwszQueueFormatName)
  279. {
  280. FormatLength = sizeof(WCHAR) * (1 + wcslen(pwszQueueFormatName));
  281. } else if (pwszQueuePathName)
  282. {
  283. PropIDs[i] = PROPID_Q_PATHNAME;
  284. PropVariants[i].vt = VT_LPWSTR;
  285. PropVariants[i].pwszVal = pwszQueuePathName;
  286. i++;
  287. }
  288. PropIDs[i] = PROPID_Q_LABEL;
  289. PropVariants[i].vt = VT_LPWSTR;
  290. PropVariants[i].pwszVal = L"MSMQ for dumpfiles";
  291. i++;
  292. QueueProps.aPropID = PropIDs;
  293. QueueProps.aPropVar = PropVariants;
  294. QueueProps.cProp = i;
  295. QueueProps.aStatus = hrProps;
  296. Hr = MQCreateQueue(NULL,
  297. &QueueProps,
  298. pwszQueueFormatName,
  299. &FormatLength);
  300. if (FAILED(Hr))
  301. {
  302. //
  303. // API Fails, not because the queue exists
  304. //
  305. if (((LONG) Hr) != MQ_ERROR_QUEUE_EXISTS)
  306. PRINTERROR("Cannot create queue", Hr);
  307. }
  308. }
  309. Hr = MQOpenQueue(pwszQueueFormatName,
  310. bSendQueue ? MQ_SEND_ACCESS : MQ_RECEIVE_ACCESS,
  311. MQ_DENY_NONE,
  312. &hQueue);
  313. if (FAILED(Hr))
  314. {
  315. PRINTERROR("MQOpenQueue failed", Hr);
  316. }
  317. if (FAILED(Hr))
  318. {
  319. PRINTERROR("Cannot open queue", Hr);
  320. }
  321. *pStartedQ = (IMSMQQueue*) hQueue;
  322. if (g_CreateQ)
  323. {
  324. *bCreated = TRUE;
  325. }
  326. return S_OK;
  327. Cleanup:
  328. return Hr;
  329. }
  330. /********************************************************************************************
  331. //
  332. // SendMSMQMessage: Sends the message string to the queue
  333. //
  334. // hSendQ QUEUEHANDLE from MQOpenQueue
  335. //
  336. // pwszMessage WCHAR array of message body to be send
  337. //
  338. // pwszMessageLabel WCHAR array specifying message label
  339. //
  340. // Returns S_OK for success
  341. //
  342. *******************************************************************************************/
  343. HRESULT
  344. SendMsmQMessage(
  345. QUEUEHANDLE hSendQ,
  346. PWCHAR pwszMessage,
  347. PWCHAR pwszMessageLabel
  348. )
  349. {
  350. HRESULT Hr = S_OK;
  351. DWORD i;
  352. #define NUM_PROPS 4
  353. MSGPROPID PropIds[NUM_PROPS];
  354. MQPROPVARIANT PropVariants[NUM_PROPS] = {0};
  355. MQMSGPROPS MsgProps = {0};
  356. HRESULT hrProps[NUM_PROPS];
  357. if (!hSendQ)
  358. {
  359. Hr = E_INVALIDARG;
  360. PRINTERROR("Invalid Send Q handle", Hr);
  361. }
  362. i = 0;
  363. PropIds[i] = PROPID_M_LABEL;
  364. PropVariants[i].vt = VT_LPWSTR;
  365. PropVariants[i].pwszVal = pwszMessageLabel;
  366. i++;
  367. PropIds[i] = PROPID_M_BODY;
  368. PropVariants[i].vt = VT_VECTOR|VT_UI1;
  369. PropVariants[i].caub.pElems = (LPBYTE) pwszMessage;
  370. PropVariants[i].caub.cElems = sizeof(WCHAR) * ( 1 + wcslen (pwszMessage) );
  371. i++;
  372. PropIds[i] = PROPID_M_BODY_TYPE;
  373. PropVariants[i].vt = VT_UI4;
  374. PropVariants[i].ulVal = VT_LPWSTR;
  375. PropIds[i] = PROPID_M_TIME_TO_BE_RECEIVED;
  376. PropVariants[i].vt = VT_UI4;
  377. PropVariants[i].ulVal = 60*5;
  378. i++;
  379. MsgProps.cProp = NUM_PROPS;
  380. MsgProps.aPropID = PropIds;
  381. MsgProps.aPropVar = PropVariants;
  382. MsgProps.aStatus = hrProps;
  383. Hr = MQSendMessage(hSendQ, &MsgProps, MQ_NO_TRANSACTION);
  384. if (Hr == MQ_ERROR_PROPERTY)
  385. {
  386. dprintf("MQProperty errors\n");
  387. for (i = 0; i < NUM_PROPS; i++)
  388. {
  389. dprintf("%lx: %8lx --> %08lx\n", i, PropIds[i], hrProps[i]);
  390. }
  391. }
  392. if (FAILED(Hr))
  393. {
  394. PRINTERROR("MQSendMessage failed", Hr);
  395. }
  396. #undef NUM_PROPS
  397. Hr = S_OK;
  398. Cleanup:
  399. return Hr;
  400. }
  401. /****************************************************************************************
  402. // This reveives message from an already opened queue.
  403. //
  404. // hReceiveQ QUEUEHANDLE from MQOpenQueue
  405. //
  406. // pwszMessageBuff WCHAR array for receiving message body
  407. //
  408. // SizeofMessageBuff size of available memory in pwszMessageBuff
  409. //
  410. // pwszMessageLabelBuff WCHAR array for receiving label associated with message
  411. //
  412. // SizeofMessageLabelBuff size of available memory in pwszMessageLabelBuff
  413. //
  414. // Returns S_OK for success
  415. //*************************************************************************************/
  416. HRESULT
  417. ReceiveMsmQMessage(
  418. QUEUEHANDLE hReceiveQ,
  419. PWCHAR pwszMessageBuff,
  420. ULONG SizeofMessageBuff,
  421. PWCHAR pwszMessageLabelBuff,
  422. ULONG SizeofMessageLabelBuff
  423. )
  424. {
  425. HRESULT Hr = S_OK;
  426. #define NUM_RCV_PROPS 5
  427. MSGPROPID PropIds[NUM_RCV_PROPS];
  428. MQPROPVARIANT PropVariants[NUM_RCV_PROPS];
  429. HRESULT hrProps[NUM_RCV_PROPS];
  430. MQMSGPROPS MessageProps;
  431. DWORD i;
  432. if (!hReceiveQ)
  433. {
  434. Hr = E_INVALIDARG;
  435. PRINTERROR("Invalid Receive Q handle", Hr);
  436. }
  437. i = 0;
  438. PropIds[i] = PROPID_M_LABEL_LEN;
  439. PropVariants[i].vt = VT_UI4;
  440. PropVariants[i].ulVal = SizeofMessageLabelBuff;
  441. i++;
  442. PropIds[i] = PROPID_M_LABEL;
  443. PropVariants[i].vt = VT_LPWSTR;
  444. PropVariants[i].pwszVal = pwszMessageLabelBuff;
  445. i++;
  446. PropIds[i] = PROPID_M_BODY_SIZE;
  447. PropVariants[i].vt = VT_UI4;
  448. i++;
  449. PropIds[i] = PROPID_M_BODY_TYPE;
  450. PropVariants[i].vt = VT_UI4;
  451. i++;
  452. PropIds[i] = PROPID_M_BODY;
  453. PropVariants[i].vt = VT_VECTOR|VT_UI1;
  454. PropVariants[i].caub.pElems = (LPBYTE) pwszMessageBuff;
  455. PropVariants[i].caub.cElems = SizeofMessageBuff;
  456. i++;
  457. MessageProps.aPropID = PropIds;
  458. MessageProps.aPropVar = PropVariants;
  459. MessageProps.aStatus = hrProps;
  460. MessageProps.cProp = i;
  461. Hr = MQReceiveMessage(hReceiveQ, -1, MQ_ACTION_RECEIVE,
  462. &MessageProps, NULL, NULL, NULL, MQ_NO_TRANSACTION);
  463. if (Hr == MQ_ERROR_PROPERTY)
  464. {
  465. dprintf("MQProperty errors\n");
  466. for (i = 0; i < NUM_RCV_PROPS; i++)
  467. {
  468. dprintf("%lx: %8lx --> %08lx\n", i, PropIds[i], hrProps[i]);
  469. }
  470. }
  471. if (FAILED(Hr))
  472. {
  473. PRINTERROR("MQReceiveMessage failed", Hr);
  474. }
  475. Cleanup:
  476. return Hr;
  477. }
  478. /******************************************************************************
  479. //
  480. // Close a MsmQ opened with MQOpenQueue
  481. //
  482. // hQueue QUEUEHANDLE from MQOpenQueue
  483. //
  484. // bDeleteQ If set TRUE , queue would be deleted
  485. //
  486. // Returns S_OK on success
  487. //
  488. /*****************************************************************************/
  489. HRESULT
  490. CloseMessageQ(
  491. QUEUEHANDLE hQueue,
  492. BOOL bDeleteQ
  493. )
  494. {
  495. HRESULT Hr = S_OK;
  496. if (!hQueue || FAILED(Hr = MQCloseQueue(hQueue)))
  497. {
  498. PRINTERROR("Cannot close queue", Hr);
  499. }
  500. if (bDeleteQ)
  501. {
  502. // XXX - need a format name
  503. // MQDeleteQueue();
  504. }
  505. if (FAILED(Hr))
  506. {
  507. PRINTERROR("Cannot delete queue", Hr);
  508. }
  509. Cleanup:
  510. return Hr;
  511. }
  512. //--------------------------------------------------------
  513. //
  514. // Receiver Mode
  515. // -------------
  516. // The receiver side does the following:
  517. // 1. Creates a queue on its given computer'
  518. // of type "guidMQTestType".
  519. // 2. Opens the queue
  520. // 3. In a Loop
  521. // Receives messages
  522. // Prints message body and message label
  523. // Launches debugger
  524. // 4. Cleanup handles
  525. // 5. Deletes the queue from the directory service
  526. //
  527. //--------------------------------------------------------
  528. HRESULT Receiver()
  529. {
  530. QUEUEHANDLE pqReceive = NULL;
  531. BSTR bstrFormatName = NULL;
  532. BSTR bstrPathName = NULL;
  533. BSTR bstrServiceType = NULL;
  534. BSTR bstrLabel = NULL;
  535. BSTR bstrMsgLabel = NULL;
  536. VARIANT varIsTransactional, varIsWorldReadable, varBody, varBody2, varWantDestQueue, varWantBody, varReceiveTimeout;
  537. WCHAR wcsPathName[1000];
  538. BOOL fQuit = FALSE;
  539. BOOL Created= FALSE;
  540. HRESULT hresult = NOERROR;
  541. dprintf("\nReceiver for queue %s on machine %s\nLimit memusage to %ld%%\n",
  542. g_QueueName,
  543. g_ServerMachine,
  544. g_MaxMemUsage);
  545. //
  546. // Prepare properties to create a queue on local machine
  547. //
  548. if (g_FormatName[0])
  549. {
  550. // access by formatname
  551. // Set the FormatName
  552. StringCbPrintfW(wcsPathName, sizeof(wcsPathName), L"%S", g_FormatName);
  553. dprintf("Openeing q byt formatname: %ws\n", wcsPathName);
  554. bstrFormatName = SysAllocString(wcsPathName);
  555. if (bstrFormatName == NULL)
  556. {
  557. PRINTERROR("OOM: formatname", E_OUTOFMEMORY);
  558. }
  559. } else
  560. {
  561. // access by pathname
  562. // Set the PathName
  563. StringCbPrintfW(wcsPathName, sizeof(wcsPathName), L"%S\\%S", g_ServerMachine,g_QueueName);
  564. dprintf("Openeing q %ws\n", wcsPathName);
  565. bstrPathName = SysAllocString(wcsPathName);
  566. if (bstrPathName == NULL)
  567. {
  568. PRINTERROR("OOM: pathname", E_OUTOFMEMORY);
  569. }
  570. }
  571. hresult = StartMessageQ(bstrFormatName, bstrPathName, FALSE,
  572. &pqReceive, &Created);
  573. if (FAILED(hresult))
  574. {
  575. PRINTERROR("Cannot start Q", hresult);
  576. }
  577. g_DumpPath[0] = 0;
  578. //
  579. // Main receiver loop
  580. //
  581. dprintf("\nWaiting for messages ...\n");
  582. while (!fQuit)
  583. {
  584. WCHAR BufferMsg[1024], BufferLabel[100];
  585. MEMORYSTATUS stat;
  586. ULONG nWaitCount;
  587. //
  588. // Receive the message
  589. //
  590. hresult = ReceiveMsmQMessage(pqReceive,BufferMsg, sizeof(BufferMsg),
  591. BufferLabel, sizeof(BufferLabel));
  592. if (FAILED(hresult))
  593. {
  594. PRINTERROR("Receive message", hresult);
  595. }
  596. dprintf("%ws : %ws\n", BufferLabel, BufferMsg);
  597. //
  598. // Check for end of app
  599. //
  600. if (_wcsicmp(BufferMsg, L"quit") == 0)
  601. {
  602. fQuit = TRUE;
  603. }
  604. else
  605. {
  606. // Launch the debugger
  607. StringCbPrintfA(g_DumpPath, sizeof(g_DumpPath), "%ws", BufferMsg);
  608. if (LaunchDebugger(FALSE) == S_OK)
  609. {
  610. // done with this dump
  611. g_DumpPath[0] = 0;
  612. }
  613. }
  614. // wait for sometime before launching another process
  615. stat.dwMemoryLoad = -1;
  616. nWaitCount = 0;
  617. while (stat.dwMemoryLoad > g_MaxMemUsage)
  618. {
  619. //
  620. //
  621. // Check CPU load and return when it's below our bound
  622. //
  623. GlobalMemoryStatus(&stat);
  624. nWaitCount++;
  625. if (stat.dwMemoryLoad > g_MaxMemUsage)
  626. {
  627. dprintf("Memory usage now is %ld%%, waiting (%ldms) for usage < %ld%%\r",
  628. stat.dwMemoryLoad,
  629. g_PauseForNext * nWaitCount,
  630. g_MaxMemUsage);
  631. if (nWaitCount > 100)
  632. {
  633. nWaitCount = 100;
  634. }
  635. }
  636. Sleep( g_PauseForNext * nWaitCount );
  637. }
  638. dprintf("Memory usage now is %ld%%, waiting for message ...\r",
  639. stat.dwMemoryLoad);
  640. } /* while (!fQuit) */
  641. // fall through...
  642. Cleanup:
  643. CloseMessageQ(pqReceive, Created);
  644. if (bstrPathName) SysFreeString(bstrPathName);
  645. if (bstrFormatName) SysFreeString(bstrFormatName);
  646. return hresult;
  647. }
  648. /************************************************************************************************
  649. //
  650. // SendMessageText - generic API to send message on an MSMQ, It opens the queue, puts message in it
  651. // and closes the queue.
  652. //
  653. // pwszMsmqFormat - Format name identifying the queue where message is to be sent
  654. //
  655. // pwszMesgLabel - Label for the message to be sent
  656. //
  657. // pwszMesgText - Message to be sent
  658. //
  659. // Reuturns S_OK on sucess
  660. //
  661. *************************************************************************************************/
  662. HRESULT
  663. SendMessageText(
  664. PWCHAR pwszMsmqFormat,
  665. PWCHAR pwszMesgLabel,
  666. PWCHAR pwszMesgText
  667. )
  668. {
  669. HRESULT Hr;
  670. BOOL Created = FALSE;
  671. QUEUEHANDLE hSendQ = NULL;
  672. Hr = StartMessageQ(pwszMsmqFormat, NULL, TRUE,
  673. &hSendQ, &Created);
  674. if (FAILED(Hr))
  675. {
  676. PRINTERROR("Cannot start Q", Hr);
  677. }
  678. SendMsmQMessage(hSendQ, pwszMesgText, pwszMesgLabel);
  679. Cleanup:
  680. CloseMessageQ(hSendQ, Created);
  681. return Hr;
  682. }
  683. void PrintError(char *s, HRESULT hr)
  684. {
  685. dprintf("Cleanup: %s (0x%X)\n", s, hr);
  686. }