/*++ Copyright (c) 1992-2001 Microsoft Corporation Module Name: mqrcvr.cpp Abstract: Receives file names from server and launches debugger --*/ // // Includes // #ifndef MQEXTDLL #include #include #include #define dprintf printf #else #include "mqext.h" #endif // // Unique include file for ActiveX MSMQ apps // #include #include #include // // Various defines // #define MAX_VAR 20 #define MAX_BUFFER 500 // // GUID created with the tool "GUIDGEN" // static WCHAR strGuidMQTestType[] = L"{c30e0960-a2c0-11cf-9785-00608cb3e80c}"; // // Prototypes // void PrintError(char *s, HRESULT hr); HRESULT Syntax(); char g_DebuggerName[MAX_PATH]; char g_SymCache[MAX_PATH]; char g_ServerMachine[MAX_COMPUTERNAME_LENGTH*4 + 1]; char g_FormatName[MAX_PATH] = {0}; char g_QueueName[100]; CHAR g_DumpPath[MAX_PATH + 1]; BOOL g_Retriage = FALSE; BOOL g_NoCustomer = FALSE; BOOL g_SendMail = FALSE; ULONG g_MaxMemUsage = 50; ULONG g_PauseForNext = 1000; BOOL g_CreateQ = 0; BOOL g_bSend = FALSE; // Some useful macros #define RELEASE(punk) if (punk) { (punk)->Release(); (punk) = NULL; } #define ADDREF(punk) ((punk) ? (punk)->AddRef() : 0) #define PRINTERROR(s, hr) { PrintError(s, hr); goto Cleanup; } BOOL GetArgs(int Argc, CHAR ** Argv) { int i = 1; g_ServerMachine[0] = 0; g_QueueName[0] = 0; StringCchCopy(g_DebuggerName, sizeof(g_DebuggerName), "c:\\Debuggers\\ocakd.exe"); StringCchCopy(g_SymCache, sizeof(g_SymCache), "c:\\symcache"); g_bSend = FALSE; while (i %08lx\n", i, PropIds[i], hrProps[i]); } } if (FAILED(Hr)) { PRINTERROR("MQSendMessage failed", Hr); } #undef NUM_PROPS Hr = S_OK; Cleanup: return Hr; } /**************************************************************************************** // This reveives message from an already opened queue. // // hReceiveQ QUEUEHANDLE from MQOpenQueue // // pwszMessageBuff WCHAR array for receiving message body // // SizeofMessageBuff size of available memory in pwszMessageBuff // // pwszMessageLabelBuff WCHAR array for receiving label associated with message // // SizeofMessageLabelBuff size of available memory in pwszMessageLabelBuff // // Returns S_OK for success //*************************************************************************************/ HRESULT ReceiveMsmQMessage( QUEUEHANDLE hReceiveQ, PWCHAR pwszMessageBuff, ULONG SizeofMessageBuff, PWCHAR pwszMessageLabelBuff, ULONG SizeofMessageLabelBuff ) { HRESULT Hr = S_OK; #define NUM_RCV_PROPS 5 MSGPROPID PropIds[NUM_RCV_PROPS]; MQPROPVARIANT PropVariants[NUM_RCV_PROPS]; HRESULT hrProps[NUM_RCV_PROPS]; MQMSGPROPS MessageProps; DWORD i; if (!hReceiveQ) { Hr = E_INVALIDARG; PRINTERROR("Invalid Receive Q handle", Hr); } i = 0; PropIds[i] = PROPID_M_LABEL_LEN; PropVariants[i].vt = VT_UI4; PropVariants[i].ulVal = SizeofMessageLabelBuff; i++; PropIds[i] = PROPID_M_LABEL; PropVariants[i].vt = VT_LPWSTR; PropVariants[i].pwszVal = pwszMessageLabelBuff; i++; PropIds[i] = PROPID_M_BODY_SIZE; PropVariants[i].vt = VT_UI4; i++; PropIds[i] = PROPID_M_BODY_TYPE; PropVariants[i].vt = VT_UI4; i++; PropIds[i] = PROPID_M_BODY; PropVariants[i].vt = VT_VECTOR|VT_UI1; PropVariants[i].caub.pElems = (LPBYTE) pwszMessageBuff; PropVariants[i].caub.cElems = SizeofMessageBuff; i++; MessageProps.aPropID = PropIds; MessageProps.aPropVar = PropVariants; MessageProps.aStatus = hrProps; MessageProps.cProp = i; Hr = MQReceiveMessage(hReceiveQ, -1, MQ_ACTION_RECEIVE, &MessageProps, NULL, NULL, NULL, MQ_NO_TRANSACTION); if (Hr == MQ_ERROR_PROPERTY) { dprintf("MQProperty errors\n"); for (i = 0; i < NUM_RCV_PROPS; i++) { dprintf("%lx: %8lx --> %08lx\n", i, PropIds[i], hrProps[i]); } } if (FAILED(Hr)) { PRINTERROR("MQReceiveMessage failed", Hr); } Cleanup: return Hr; } /****************************************************************************** // // Close a MsmQ opened with MQOpenQueue // // hQueue QUEUEHANDLE from MQOpenQueue // // bDeleteQ If set TRUE , queue would be deleted // // Returns S_OK on success // /*****************************************************************************/ HRESULT CloseMessageQ( QUEUEHANDLE hQueue, BOOL bDeleteQ ) { HRESULT Hr = S_OK; if (!hQueue || FAILED(Hr = MQCloseQueue(hQueue))) { PRINTERROR("Cannot close queue", Hr); } if (bDeleteQ) { // XXX - need a format name // MQDeleteQueue(); } if (FAILED(Hr)) { PRINTERROR("Cannot delete queue", Hr); } Cleanup: return Hr; } //-------------------------------------------------------- // // Receiver Mode // ------------- // The receiver side does the following: // 1. Creates a queue on its given computer' // of type "guidMQTestType". // 2. Opens the queue // 3. In a Loop // Receives messages // Prints message body and message label // Launches debugger // 4. Cleanup handles // 5. Deletes the queue from the directory service // //-------------------------------------------------------- HRESULT Receiver() { QUEUEHANDLE pqReceive = NULL; BSTR bstrFormatName = NULL; BSTR bstrPathName = NULL; BSTR bstrServiceType = NULL; BSTR bstrLabel = NULL; BSTR bstrMsgLabel = NULL; VARIANT varIsTransactional, varIsWorldReadable, varBody, varBody2, varWantDestQueue, varWantBody, varReceiveTimeout; WCHAR wcsPathName[1000]; BOOL fQuit = FALSE; BOOL Created= FALSE; HRESULT hresult = NOERROR; dprintf("\nReceiver for queue %s on machine %s\nLimit memusage to %ld%%\n", g_QueueName, g_ServerMachine, g_MaxMemUsage); // // Prepare properties to create a queue on local machine // if (g_FormatName[0]) { // access by formatname // Set the FormatName StringCbPrintfW(wcsPathName, sizeof(wcsPathName), L"%S", g_FormatName); dprintf("Openeing q byt formatname: %ws\n", wcsPathName); bstrFormatName = SysAllocString(wcsPathName); if (bstrFormatName == NULL) { PRINTERROR("OOM: formatname", E_OUTOFMEMORY); } } else { // access by pathname // Set the PathName StringCbPrintfW(wcsPathName, sizeof(wcsPathName), L"%S\\%S", g_ServerMachine,g_QueueName); dprintf("Openeing q %ws\n", wcsPathName); bstrPathName = SysAllocString(wcsPathName); if (bstrPathName == NULL) { PRINTERROR("OOM: pathname", E_OUTOFMEMORY); } } hresult = StartMessageQ(bstrFormatName, bstrPathName, FALSE, &pqReceive, &Created); if (FAILED(hresult)) { PRINTERROR("Cannot start Q", hresult); } g_DumpPath[0] = 0; // // Main receiver loop // dprintf("\nWaiting for messages ...\n"); while (!fQuit) { WCHAR BufferMsg[1024], BufferLabel[100]; MEMORYSTATUS stat; ULONG nWaitCount; // // Receive the message // hresult = ReceiveMsmQMessage(pqReceive,BufferMsg, sizeof(BufferMsg), BufferLabel, sizeof(BufferLabel)); if (FAILED(hresult)) { PRINTERROR("Receive message", hresult); } dprintf("%ws : %ws\n", BufferLabel, BufferMsg); // // Check for end of app // if (_wcsicmp(BufferMsg, L"quit") == 0) { fQuit = TRUE; } else { // Launch the debugger StringCbPrintfA(g_DumpPath, sizeof(g_DumpPath), "%ws", BufferMsg); if (LaunchDebugger(FALSE) == S_OK) { // done with this dump g_DumpPath[0] = 0; } } // wait for sometime before launching another process stat.dwMemoryLoad = -1; nWaitCount = 0; while (stat.dwMemoryLoad > g_MaxMemUsage) { // // // Check CPU load and return when it's below our bound // GlobalMemoryStatus(&stat); nWaitCount++; if (stat.dwMemoryLoad > g_MaxMemUsage) { dprintf("Memory usage now is %ld%%, waiting (%ldms) for usage < %ld%%\r", stat.dwMemoryLoad, g_PauseForNext * nWaitCount, g_MaxMemUsage); if (nWaitCount > 100) { nWaitCount = 100; } } Sleep( g_PauseForNext * nWaitCount ); } dprintf("Memory usage now is %ld%%, waiting for message ...\r", stat.dwMemoryLoad); } /* while (!fQuit) */ // fall through... Cleanup: CloseMessageQ(pqReceive, Created); if (bstrPathName) SysFreeString(bstrPathName); if (bstrFormatName) SysFreeString(bstrFormatName); return hresult; } /************************************************************************************************ // // SendMessageText - generic API to send message on an MSMQ, It opens the queue, puts message in it // and closes the queue. // // pwszMsmqFormat - Format name identifying the queue where message is to be sent // // pwszMesgLabel - Label for the message to be sent // // pwszMesgText - Message to be sent // // Reuturns S_OK on sucess // *************************************************************************************************/ HRESULT SendMessageText( PWCHAR pwszMsmqFormat, PWCHAR pwszMesgLabel, PWCHAR pwszMesgText ) { HRESULT Hr; BOOL Created = FALSE; QUEUEHANDLE hSendQ = NULL; Hr = StartMessageQ(pwszMsmqFormat, NULL, TRUE, &hSendQ, &Created); if (FAILED(Hr)) { PRINTERROR("Cannot start Q", Hr); } SendMsmQMessage(hSendQ, pwszMesgText, pwszMesgLabel); Cleanup: CloseMessageQ(hSendQ, Created); return Hr; } void PrintError(char *s, HRESULT hr) { dprintf("Cleanup: %s (0x%X)\n", s, hr); }