📄 jcmd.c
字号:
return nReturn;}/* * TestSinglePath() * This function is called by the main routine to test the data * representing a single full path for the existence of a file. * It delegates actual file name testing to either TestSingleExt() * or TestMultiExt(), depending on whether a given full path ends * with a file extension. */int TestSinglePath(PJCMD_EXEC_DATA pData){ PJCMD_TEST_FUNC testFunc = pData->hasExt ? &TestSingleExt : &TestMultiExt; strcpy(pData->szTestPath, pData->execPath); return testFunc(pData);}/* * TestMultiPath() * This function is called by the main routine to test the data * representing a file name where no path is given. The function * iterates through various possibilities for a full path. The * order of the iteration emulates the file search protocol of the * standard command interpreter, including the system path. (One * exception in this version is that the 16-bit Windows directory, * usually named C:\WINNT\System, is not searched in Windows NT and * Windows 2000. For each test path, the function calls TestSingleExt() * or TestMultiExt(), depending on whether a given full path ends with * a file extension. */int TestMultiPath(PJCMD_EXEC_DATA pData){ DWORD dwLength; int nReturn; char *pPath; PJCMD_TEST_FUNC testFunc = pData->hasExt ? &TestSingleExt : &TestMultiExt; /* order of search */ /* (1) Current directory */ dwLength = GetCurrentDirectory(MAX_PATH, pData->szTestPath); nReturn = testFunc(pData); if(nReturn == 1) return 1; /* (2) Windows system directory */ dwLength = GetSystemDirectory(pData->szTestPath, MAX_PATH); nReturn = testFunc(pData); if(nReturn == 1) return 1; /* (3) System path, one-by-one */ pPath = ExtractExt(pData->szTestPath, pData->pPaths); while(pPath != 0 && *pPath != 0 && *(pData->szTestPath) != 0) { nReturn = testFunc(pData); if(nReturn == 1) break; pPath = ExtractExt(pData->szTestPath, pPath); } return nReturn;}/* * FindConsoleWindow() * This callback function is called on each top-level window in * the main thread of a process created by LaunchCommand(). It * looks for one of the two window class names used by versions * of Windows for console windows. If a console window is found, * the TESTCONSOLE structure to which the lparam parameter points * receives the handle of the console window. The count element * of the structure is incremented for the window being examined. */int CALLBACK FindConsoleWindow(HWND hwnd, LPARAM lparam){ char window_class[32]; PTESTCONSOLE ptest = (PTESTCONSOLE)lparam; ++ptest->nCount; GetClassName(hwnd, window_class, sizeof (window_class)); if(strcmp(window_class, "ConsoleWindowClass") == 0 || strcmp(window_class, "tty") == 0) { ptest->hwnd = hwnd; /* * We found what we were looking for; returning 0 * will end the iteration in EnumThreadWindows */ return 0; } return 1;}/* * CloseThreadWindow() * This callback function examines the window to determine * whether it is a candidate for closing. A candidate must be * a frame window having the following characteristics: * (1) a top-level window; * (2) without an owner; * (3) lacking the WS_POPUP style. * To close the window, the function first sends it a WM_CLOSE * message. If that doesn't work, it sends a system command message * to close (similar to pressing Alt-F4). If that doesn't work, * the method reports failure and the main routine will * terminate the window's process. */int CALLBACK CloseThreadWindow(HWND hwnd, LPARAM lparam){ HWND hwndParent, hwndPopup; /* unused */ lparam; if(!IsWindow(hwnd)) return 1; while((hwndParent = GetParent(hwnd)) != 0) { /* * In the unlikely event that a popup child window * was immediately activated, we will first close * the popup */ hwndPopup = GetLastActivePopup(hwndParent); if(hwndPopup != hwndParent) { SendMessage(hwndPopup, WM_QUIT, 0, 0); } hwnd = hwndParent; } if(GetWindow(hwnd, GW_OWNER) == 0) { DWORD dwStyle = GetWindowLong(hwnd, GWL_STYLE); if(dwStyle != 0 && (dwStyle & WS_POPUP) == 0) { SendMessage(hwnd, WM_CLOSE, 0, 0); if(IsWindow(hwnd)) SendMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0); /* Whether it worked or not, we are done * iterating through windows. */ return 0; } } return 1;}/* * FoundConsole() * We have a console if: * (1) we could not find any windows (because the console * window is built-in under some versions of Windows); or * (2) we found a window from one of the two console window * classes used by windows - FindConsole() put that window's * handle into the TESTCONSOLE structure. */int FoundConsole(PTESTCONSOLE pt){ return pt->nCount == 0 || pt->hwnd != 0;}/* IsExec() * Returns 1 if string ends with an executable extension * and 0 otherwise. */int IsExec(char* szFileName){ char *pDot; if(szFileName == 0 || (pDot = strrchr(szFileName, '.')) == 0) return 0; if(stricmp(pDot, ".exe") == 0) return 1; if(stricmp(pDot, ".bat") == 0) return 1; if(stricmp(pDot, ".cmd") == 0) return 1; if(stricmp(pDot, ".com") == 0) return 1; return 0;}/* * ExtractExt() * This customized parsing routine extracts a single file extension * from a string of extensions separated by semicolons. The return * value points to the location to start the next extraction. */char* ExtractExt(/* [out] */ char* pPathExt, /* [in] */char* pExt){ int extLen, extLenNoQuote; if(*pExt == ';') ++pExt; if(*pExt == '\"') ++pExt; extLen = strcspn(pExt, ";"); extLenNoQuote = extLen; if(extLen != 0 && *(pExt + extLen - 1) == '\"') --extLenNoQuote; *pPathExt = 0; strncat(pPathExt, pExt, extLenNoQuote); return pExt + extLen;}/* * MakeFileAssoc() * This function finds the command associated with the input * file's extension (if one exists) and interprets the resulting * command string to insert the input file and perform substitution * of environment variables. If no association can be found, the * output file is a copy of the input file. */void MakeFileAssoc(/* [out] */ char* szDest, /* [in] */ char* szSource){ char *pExt, szKey[1024], szVerb[32]; const int nKeyLength = 1024; const int nVerbLength = 32; int nSuccess = 0; HKEY hKey = 0; DWORD dwLength = nKeyLength; pExt = strrchr(szSource, '\\'); pExt = (pExt == 0) ? 0 : strrchr(pExt, '.'); if(pExt != 0) { nSuccess = RegOpenKeyEx(HKEY_CLASSES_ROOT, pExt, 0, KEY_READ, &hKey); if(nSuccess == ERROR_SUCCESS) { nSuccess = RegQueryValueEx(hKey, 0, 0, 0, (unsigned char*)szKey, &dwLength); if(nSuccess == ERROR_SUCCESS && dwLength != 0) { RegCloseKey(hKey); hKey = 0; strcat(szKey, "\\shell"); nSuccess = RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hKey); if(nSuccess == ERROR_SUCCESS) { dwLength = nVerbLength; nSuccess = RegQueryValueEx(hKey, 0, 0, 0, (unsigned char*)szVerb, &dwLength); if(nSuccess != ERROR_SUCCESS || dwLength == 0) { strcpy(szVerb, "open"); } RegCloseKey(hKey); hKey = 0; strcat(szKey, "\\"); strcat(szKey, szVerb); strcat(szKey, "\\command"); nSuccess = RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hKey); if(nSuccess == ERROR_SUCCESS) { dwLength = nKeyLength; nSuccess = RegQueryValueEx(hKey, 0, 0, 0, (unsigned char*)szKey, &dwLength); } } } } if(hKey != 0) { RegCloseKey(hKey); } if(nSuccess == ERROR_SUCCESS && dwLength != 0) { char szExpanded[1024]; memset(szExpanded, 0, 1024); ExpandEnvironmentStrings(szKey, szExpanded, 1024); pExt = strstr(szExpanded, "%1"); if(pExt != 0) { dwLength = pExt - szExpanded; strncpy(szDest, szExpanded, dwLength); *(szDest + dwLength) = 0; strcat(szDest, szSource); if(strlen(pExt) > 0) strcat(szDest, (pExt + 2)); } } } if(pExt == 0 || nSuccess != ERROR_SUCCESS) { strcpy(szDest, szSource); }}/* * WriteProcessError() * This function writes a system error message to * the stream referenced by the handle. */void WriteProcessError(HANDLE handle){ char szMsg[256]; LPVOID lpMsgBuf; strcpy(szMsg, "Could not create jcmd process: "); FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR) &lpMsgBuf, 0, NULL ); strcat(szMsg, (LPCSTR)lpMsgBuf); LocalFree(lpMsgBuf); WriteMessage(szMsg, handle);}/* * WriteMessage() * This methods writes a string to a resource represented by the * handle parameter. It is used in jcmd to write data to the * standard error stream. */void WriteMessage(char* szMsg, HANDLE handle){ DWORD dwLength; WriteFile(handle, szMsg, strlen(szMsg), &dwLength, 0);}/* ImputThreadProc() * Waits for and reads input from calling process */DWORD WINAPI InputThreadProc(LPVOID lp){ const char CTRL_C = (char)3; PJCMD_EXEC_DATA pData = (PJCMD_EXEC_DATA)lp; HANDLE hStdInput = GetStdHandle(STD_INPUT_HANDLE); HANDLE hStdOutput = pData->si.hStdOutput; char ch = 0; DWORD dwBytesRead; int nSuccess; WriteMessage("InputThreadProc started...\n", hStdOutput); while(1) { nSuccess = ReadFile(hStdInput, (LPVOID)&ch, 1, &dwBytesRead, 0); if(nSuccess && ch == CTRL_C) { WriteMessage("Ctrl-C received.\n", hStdOutput); /* terminate child process */ TerminateProcess(pData->pi.hProcess, 1); break; } } return 1;}/* end jcmd2.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -