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.

315 lines
9.6 KiB

  1. #include <Windows.h>
  2. #include <objBase.h>
  3. #include <stdio.h>
  4. #include <mqoai.h> // MSMQ include file
  5. // Existing code
  6. //-----------------------------------------------------
  7. //
  8. // Check if local computer is DS enabled or DS disabled
  9. //
  10. //-----------------------------------------------------
  11. short DetectDsConnection(void)
  12. {
  13. IMSMQApplication2 *pqapp = NULL;
  14. short fDsConnection;
  15. HRESULT hresult;
  16. hresult = CoCreateInstance(
  17. CLSID_MSMQApplication,
  18. NULL, // punkOuter
  19. CLSCTX_SERVER,
  20. IID_IMSMQApplication2,
  21. (LPVOID *)&pqapp);
  22. if (FAILED(hresult))
  23. PRINTERROR("Cannot create application", hresult);
  24. pqapp->get_IsDsEnabled(&fDsConnection);
  25. Cleanup:
  26. RELEASE(pqapp);
  27. return fDsConnection;
  28. }
  29. // Split this routine into initialize and get next file path
  30. //--------------------------------------------------------
  31. //
  32. // Receiver Mode
  33. // -------------
  34. // The receiver side does the following:
  35. // 1. Creates a queue on its given computer'
  36. // of type "guidMQTestType".
  37. // 2. Opens the queue
  38. // 3. In a Loop
  39. // Receives messages
  40. // Prints message body and message label
  41. // Launches debugger
  42. // 4. Cleanup handles
  43. // 5. Deletes the queue from the directory service
  44. //
  45. //--------------------------------------------------------
  46. // rename this function to reciever
  47. HRESULT CMessageQueue::Initialize(/* send connect params*/)
  48. {
  49. IMSMQMessage *pmessageReceive = NULL;
  50. IMSMQQueue *pqReceive = NULL;
  51. IMSMQQueueInfo *pqinfo = NULL;
  52. BSTR bstrPathName = NULL;
  53. BSTR bstrServiceType = NULL;
  54. BSTR bstrLabel = NULL;
  55. BSTR bstrMsgLabel = NULL;
  56. VARIANT varIsTransactional, varIsWorldReadable, varBody, varBody2, varWantDestQueue, varWantBody, varReceiveTimeout;
  57. WCHAR wcsPathName[1000];
  58. BOOL fQuit = FALSE;
  59. HRESULT hresult = NOERROR;
  60. /* printf("\nReceiver for queue %s on machine %s\nLimit memusage to %ld%%\n",
  61. g_QueueName,
  62. g_ServerMachine,
  63. g_MaxMemUsage);
  64. */
  65. //
  66. // Create MSMQQueueInfo object
  67. //
  68. hresult = CoCreateInstance(
  69. CLSID_MSMQQueueInfo,
  70. NULL, // punkOuter
  71. CLSCTX_SERVER,
  72. IID_IMSMQQueueInfo,
  73. (LPVOID *)&pqinfo);
  74. if (FAILED(hresult))
  75. {
  76. //PRINTERROR("Cannot create queue instance", hresult);
  77. }
  78. //
  79. // Prepare properties to create a queue on local machine
  80. //
  81. if (g_FormatName[0])
  82. {
  83. // access by formatname
  84. // Set the FormatName
  85. swprintf(wcsPathName, L"DIRECT=%S\\%S", g_FormatName,g_QueueName);
  86. //printf("Openeing q byt formatname: %ws\n", wcsPathName);
  87. bstrPathName = SysAllocString(wcsPathName);
  88. if (bstrPathName == NULL)
  89. {
  90. // PRINTERROR("OOM: formatname", E_OUTOFMEMORY);
  91. }
  92. pqinfo->put_FormatName(bstrPathName);
  93. } else
  94. {
  95. // access by pathname
  96. // Set the PathName
  97. swprintf(wcsPathName, L"%S\\%S", g_ServerMachine,g_QueueName);
  98. //printf("Openeing q %ws\n", wcsPathName);
  99. bstrPathName = SysAllocString(wcsPathName);
  100. if (bstrPathName == NULL)
  101. {
  102. // PRINTERROR("OOM: pathname", E_OUTOFMEMORY);
  103. }
  104. pqinfo->put_PathName(bstrPathName);
  105. }
  106. //
  107. // Set the type of the queue
  108. // (Will be used to locate all the queues of this type)
  109. //
  110. bstrServiceType = SysAllocString(strGuidMQTestType);
  111. if (bstrServiceType == NULL)
  112. {
  113. PRINTERROR("OOM: ServiceType", E_OUTOFMEMORY);
  114. }
  115. pqinfo->put_ServiceTypeGuid(bstrServiceType);
  116. //
  117. // Put a description to the queue
  118. // (Useful for administration through the MSMQ admin tools)
  119. //
  120. bstrLabel =
  121. SysAllocString(L"MSMQ for dumpfiles");
  122. if (bstrLabel == NULL)
  123. {
  124. //PRINTERROR("OOM: label ", E_OUTOFMEMORY);
  125. }
  126. pqinfo->put_Label(bstrLabel);
  127. //
  128. // specify if transactional
  129. //
  130. VariantInit(&varIsTransactional);
  131. varIsTransactional.vt = VT_BOOL;
  132. varIsTransactional.boolVal = MQ_TRANSACTIONAL_NONE;
  133. VariantInit(&varIsWorldReadable);
  134. varIsWorldReadable.vt = VT_BOOL;
  135. varIsWorldReadable.boolVal = FALSE;
  136. //
  137. // create the queue
  138. //
  139. if (g_CreateQ)
  140. {
  141. hresult = pqinfo->Create(&varIsTransactional, &varIsWorldReadable);
  142. if (FAILED(hresult))
  143. {
  144. //
  145. // API Fails, not because the queue exists
  146. //
  147. if (hresult != MQ_ERROR_QUEUE_EXISTS)
  148. // PRINTERROR("Cannot create queue", hresult);
  149. }
  150. }
  151. //
  152. // Open the queue for receive access
  153. //
  154. hresult = pqinfo->Open(MQ_RECEIVE_ACCESS,
  155. MQ_DENY_NONE,
  156. &pqReceive);
  157. //
  158. // Little bit tricky. MQCreateQueue succeeded but, in case
  159. // it's a public queue, it does not mean that MQOpenQueue
  160. // will, because of replication delay. The queue is registered
  161. // in MQIS, but it might take a replication interval
  162. // until the replica reaches the server I am connected to.
  163. // To overcome this, open the queue in a loop.
  164. //
  165. // (in this specific case, this can happen only if this
  166. // program is run on a Backup Server Controller - BSC, or on
  167. // a client connected to a BSC)
  168. // To be totally on the safe side, we should have put some code
  169. // to exit the loop after a few retries, but hey, this is just a sample.
  170. //
  171. while (hresult == MQ_ERROR_QUEUE_NOT_FOUND && iCurrentRetry < g_MaxRetry)
  172. {
  173. // printf(".");
  174. fflush(stdout);
  175. // Wait a bit
  176. Sleep(500);
  177. // And retry
  178. hresult = pqinfo->Open(MQ_RECEIVE_ACCESS,
  179. MQ_DENY_NONE,
  180. &pqReceive);
  181. }
  182. if (FAILED(hresult))
  183. {
  184. // PRINTERROR("Cannot open queue", hresult);
  185. //We sould stop here
  186. }
  187. g_DumpPath[0] = 0;
  188. //
  189. // Main receiver loop
  190. //
  191. // printf("\nWaiting for messages ...\n");
  192. // while (!fQuit)
  193. // {
  194. // MEMORYSTATUS stat;
  195. //--------------------------------------------------------------------------------------//
  196. // this goes into GetNextFilePath()
  197. //--------------------------------------------------------------------------------------//
  198. ULONG nWaitCount;
  199. //
  200. // Receive the message
  201. //
  202. VariantInit(&varWantDestQueue);
  203. VariantInit(&varWantBody);
  204. VariantInit(&varReceiveTimeout);
  205. varWantDestQueue.vt = VT_BOOL;
  206. varWantDestQueue.boolVal = TRUE; // yes we want the dest queue
  207. varWantBody.vt = VT_BOOL;
  208. varWantBody.boolVal = TRUE; // yes we want the msg body
  209. varReceiveTimeout.vt = VT_I4;
  210. varReceiveTimeout.lVal = INFINITE; // infinite timeout <--- This needs to be set to a reasonable value so that we
  211. // can bounce between queues.
  212. hresult = pqReceive->Receive(
  213. NULL,
  214. &varWantDestQueue,
  215. &varWantBody,
  216. &varReceiveTimeout,
  217. &pmessageReceive);
  218. if (FAILED(hresult))
  219. {
  220. // PRINTERROR("Receive message", hresult);
  221. // we should stop here
  222. }
  223. //
  224. // Display the received message
  225. //
  226. pmessageReceive->get_Label(&bstrMsgLabel);
  227. VariantInit(&varBody);
  228. VariantInit(&varBody2);
  229. hresult = pmessageReceive->get_Body(&varBody);
  230. if (FAILED(hresult))
  231. {
  232. // PRINTERROR("can't get body", hresult);
  233. //log event nd exit
  234. }
  235. hresult = VariantChangeType(&varBody2,
  236. &varBody,
  237. 0,
  238. VT_BSTR);
  239. if (FAILED(hresult))
  240. {
  241. // PRINTERROR("can't convert message to string.", hresult);
  242. // log event and exit
  243. }
  244. VariantClear(&varBody);
  245. VariantClear(&varBody2);
  246. //
  247. // release the current message
  248. //
  249. RELEASE(pmessageReceive);
  250. //
  251. // Cleanup - Close handle to the queue
  252. //
  253. pqReceive->Close();
  254. if (FAILED(hresult))
  255. {
  256. // PRINTERROR("Cannot close queue", hresult);
  257. // Log Error and Exit
  258. }
  259. //-----------------------------------------------------------------------------------//
  260. // This code goes in the constructor.
  261. //-----------------------------------------------------------------------------------//
  262. // Move this to class destructor
  263. // Finish - Let's delete the queue from the directory service
  264. // (We don't need to do it. In case of a public queue, leaving
  265. // it in the DS enables sender applications to send messages
  266. // even if the receiver is not available.)
  267. //
  268. hresult = pqinfo->Delete();
  269. if (FAILED(hresult))
  270. {
  271. PRINTERROR("Cannot delete queue", hresult);
  272. }
  273. // fall through...
  274. Cleanup:
  275. SysFreeString(bstrPathName);
  276. SysFreeString(bstrMsgLabel);
  277. SysFreeString(bstrServiceType);
  278. SysFreeString(bstrLabel);
  279. RELEASE(pmessageReceive);
  280. RELEASE(pqReceive);
  281. RELEASE(pqinfo);
  282. return hresult;
  283. */
  284. }