Merge branch 'upstream-kwsys' into update-kwsys
This commit is contained in:
commit
e33fa5b678
|
@ -116,7 +116,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
|
||||||
SET(KWSYS_USE_MD5 1)
|
SET(KWSYS_USE_MD5 1)
|
||||||
SET(KWSYS_USE_Process 1)
|
SET(KWSYS_USE_Process 1)
|
||||||
SET(KWSYS_USE_RegularExpression 1)
|
SET(KWSYS_USE_RegularExpression 1)
|
||||||
SET(KWSYS_USE_Registry 1)
|
|
||||||
SET(KWSYS_USE_System 1)
|
SET(KWSYS_USE_System 1)
|
||||||
SET(KWSYS_USE_SystemTools 1)
|
SET(KWSYS_USE_SystemTools 1)
|
||||||
SET(KWSYS_USE_CommandLineArguments 1)
|
SET(KWSYS_USE_CommandLineArguments 1)
|
||||||
|
@ -762,7 +761,7 @@ SET(KWSYS_HXX_FILES Configure String
|
||||||
# Add selected C++ classes.
|
# Add selected C++ classes.
|
||||||
SET(cppclasses
|
SET(cppclasses
|
||||||
Directory DynamicLoader Glob RegularExpression SystemTools
|
Directory DynamicLoader Glob RegularExpression SystemTools
|
||||||
CommandLineArguments Registry IOStream SystemInformation
|
CommandLineArguments IOStream SystemInformation
|
||||||
)
|
)
|
||||||
FOREACH(cpp ${cppclasses})
|
FOREACH(cpp ${cppclasses})
|
||||||
IF(KWSYS_USE_${cpp})
|
IF(KWSYS_USE_${cpp})
|
||||||
|
@ -800,12 +799,8 @@ SET(KWSYS_CXX_SRCS)
|
||||||
# Add the proper sources for this platform's Process implementation.
|
# Add the proper sources for this platform's Process implementation.
|
||||||
IF(KWSYS_USE_Process)
|
IF(KWSYS_USE_Process)
|
||||||
IF(NOT UNIX)
|
IF(NOT UNIX)
|
||||||
# Use the Windows implementation. We need the encoded forwarding executable.
|
# Use the Windows implementation.
|
||||||
SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessWin32.c
|
SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessWin32.c)
|
||||||
${PROJECT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c)
|
|
||||||
SET_SOURCE_FILES_PROPERTIES(
|
|
||||||
${PROJECT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c
|
|
||||||
PROPERTIES GENERATED 1)
|
|
||||||
ELSE(NOT UNIX)
|
ELSE(NOT UNIX)
|
||||||
# Use the UNIX implementation.
|
# Use the UNIX implementation.
|
||||||
SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessUNIX.c)
|
SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessUNIX.c)
|
||||||
|
@ -937,43 +932,6 @@ IF(KWSYS_USE_String)
|
||||||
COMPILE_FLAGS "-DKWSYS_STRING_C")
|
COMPILE_FLAGS "-DKWSYS_STRING_C")
|
||||||
ENDIF(KWSYS_USE_String)
|
ENDIF(KWSYS_USE_String)
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
|
||||||
# Process execution on windows needs to build a forwarding executable
|
|
||||||
# that works around a Win9x bug. We encode the executable into a C
|
|
||||||
# file and build it into the library. Win9x platforms reproduce the
|
|
||||||
# executable into a temporary directory when it is needed.
|
|
||||||
IF(KWSYS_USE_Process)
|
|
||||||
IF(NOT UNIX)
|
|
||||||
# Build the forwarding executable itself and a program that will
|
|
||||||
# encode it into a C file.
|
|
||||||
ADD_EXECUTABLE(${KWSYS_NAMESPACE}ProcessFwd9x ProcessFwd9x.c)
|
|
||||||
ADD_EXECUTABLE(${KWSYS_NAMESPACE}EncodeExecutable EncodeExecutable.c)
|
|
||||||
SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}ProcessFwd9x PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}EncodeExecutable PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}ProcessFwd9x PROPERTY LABELS ${KWSYS_LABELS_EXE})
|
|
||||||
SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}EncodeExecutable PROPERTY LABELS ${KWSYS_LABELS_EXE})
|
|
||||||
|
|
||||||
SET(CFG_INTDIR "/${CMAKE_CFG_INTDIR}")
|
|
||||||
IF(CMAKE_BUILD_TOOL MATCHES "make")
|
|
||||||
SET(CFG_INTDIR "")
|
|
||||||
ENDIF(CMAKE_BUILD_TOOL MATCHES "make")
|
|
||||||
|
|
||||||
# Take advantage of a better custom command syntax if possible.
|
|
||||||
SET(CMD ${CMAKE_CURRENT_BINARY_DIR}${CFG_INTDIR}/${KWSYS_NAMESPACE}EncodeExecutable.exe)
|
|
||||||
SET(FWD ${CMAKE_CURRENT_BINARY_DIR}${CFG_INTDIR}/${KWSYS_NAMESPACE}ProcessFwd9x.exe)
|
|
||||||
ADD_CUSTOM_COMMAND(
|
|
||||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c
|
|
||||||
COMMAND ${CMD}
|
|
||||||
ARGS ${FWD} ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c
|
|
||||||
${KWSYS_NAMESPACE} ProcessFwd9x
|
|
||||||
DEPENDS ${CMD} ${FWD})
|
|
||||||
|
|
||||||
# Make sure build occurs in proper order.
|
|
||||||
ADD_DEPENDENCIES(${KWSYS_NAMESPACE} ${KWSYS_NAMESPACE}ProcessFwd9x
|
|
||||||
${KWSYS_NAMESPACE}EncodeExecutable)
|
|
||||||
ENDIF(NOT UNIX)
|
|
||||||
ENDIF(KWSYS_USE_Process)
|
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
# Setup testing if not being built as part of another project.
|
# Setup testing if not being built as part of another project.
|
||||||
IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
|
IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
|
||||||
|
@ -1012,7 +970,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
|
||||||
)
|
)
|
||||||
ENDIF(NOT WATCOM)
|
ENDIF(NOT WATCOM)
|
||||||
SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
|
SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
|
||||||
testRegistry
|
|
||||||
testIOS
|
testIOS
|
||||||
testSystemTools
|
testSystemTools
|
||||||
testCommandLineArguments
|
testCommandLineArguments
|
||||||
|
@ -1116,8 +1073,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
|
||||||
# We expect test to fail
|
# We expect test to fail
|
||||||
SET_TESTS_PROPERTIES(kwsys.testFail PROPERTIES WILL_FAIL ON)
|
SET_TESTS_PROPERTIES(kwsys.testFail PROPERTIES WILL_FAIL ON)
|
||||||
GET_TEST_PROPERTY(kwsys.testFail WILL_FAIL wfv)
|
GET_TEST_PROPERTY(kwsys.testFail WILL_FAIL wfv)
|
||||||
SET_TESTS_PROPERTIES(kwsys.testRegistry PROPERTIES FAIL_REGULAR_EXPRESSION "ERROR_NOT_VALGRIND;FAIL;Test failed")
|
|
||||||
SET_TESTS_PROPERTIES(kwsys.testRegistry PROPERTIES PASS_REGULAR_EXPRESSION "Test passed")
|
|
||||||
SET_TESTS_PROPERTIES(kwsys.testFail PROPERTIES MEASUREMENT "Some Key=Some Value")
|
SET_TESTS_PROPERTIES(kwsys.testFail PROPERTIES MEASUREMENT "Some Key=Some Value")
|
||||||
MESSAGE(STATUS "GET_TEST_PROPERTY returned: ${wfv}")
|
MESSAGE(STATUS "GET_TEST_PROPERTY returned: ${wfv}")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
|
@ -1,114 +0,0 @@
|
||||||
/*============================================================================
|
|
||||||
KWSys - Kitware System Library
|
|
||||||
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
|
|
||||||
|
|
||||||
Distributed under the OSI-approved BSD License (the "License");
|
|
||||||
see accompanying file Copyright.txt for details.
|
|
||||||
|
|
||||||
This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
||||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
See the License for more information.
|
|
||||||
============================================================================*/
|
|
||||||
#include <stdio.h>
|
|
||||||
#ifdef __WATCOMC__
|
|
||||||
#define _unlink unlink
|
|
||||||
#endif
|
|
||||||
int main(int argc, char* argv[])
|
|
||||||
{
|
|
||||||
FILE* ifp;
|
|
||||||
FILE* ofp;
|
|
||||||
int i;
|
|
||||||
int n;
|
|
||||||
int count = 0;
|
|
||||||
unsigned char buffer[1024];
|
|
||||||
|
|
||||||
/* Check arguments. */
|
|
||||||
if(argc != 5)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Usage: %s <input> <output> <kwsys-name> <array>\n",
|
|
||||||
argv[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open the input file. */
|
|
||||||
ifp = fopen(argv[1], "rb");
|
|
||||||
if(!ifp)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Cannot open input file: \"%s\"\n", argv[1]);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
ofp = fopen(argv[2], "w");
|
|
||||||
if(!ofp)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Cannot open output file: \"%s\"\n", argv[2]);
|
|
||||||
fclose(ifp);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prepend header comment. */
|
|
||||||
fprintf(ofp, "/*\n * DO NOT EDIT\n * This file is generated by:\n");
|
|
||||||
fprintf(ofp, " * %s\n */\n\n", argv[0]);
|
|
||||||
fprintf(ofp, "#include \"kwsysPrivate.h\"\n");
|
|
||||||
fprintf(ofp, "#include KWSYS_HEADER(Configure.h)\n\n");
|
|
||||||
fprintf(ofp, "#include <stdio.h>\n\n");
|
|
||||||
fprintf(ofp, "#if defined(_WIN32)\n");
|
|
||||||
fprintf(ofp, "# include <io.h>\n");
|
|
||||||
fprintf(ofp, "#else\n");
|
|
||||||
fprintf(ofp, "# include <unistd.h>\n");
|
|
||||||
fprintf(ofp, "#endif\n");
|
|
||||||
fprintf(ofp, "\n");
|
|
||||||
fprintf(ofp, "static void kwsys_unlink(const char* fname)\n");
|
|
||||||
fprintf(ofp, "{\n");
|
|
||||||
fprintf(ofp, "#if defined(__WATCOMC__)\n");
|
|
||||||
fprintf(ofp, " unlink(fname);\n");
|
|
||||||
fprintf(ofp, "#else\n");
|
|
||||||
fprintf(ofp, " _unlink(fname);\n");
|
|
||||||
fprintf(ofp, "#endif\n");
|
|
||||||
fprintf(ofp, "}\n");
|
|
||||||
fprintf(ofp, "\n");
|
|
||||||
|
|
||||||
/* Split file up in 1024-byte chunks. */
|
|
||||||
while((n = (int)fread(buffer, 1, 1024, ifp)) > 0)
|
|
||||||
{
|
|
||||||
fprintf(ofp, "static unsigned char kwsysEncodedArray%s_%d[%d] = {\n",
|
|
||||||
argv[4], count++, n);
|
|
||||||
for(i=0; i < n-1; ++i)
|
|
||||||
{
|
|
||||||
fprintf(ofp, "0x%02X", buffer[i]);
|
|
||||||
if(i%10 == 9)
|
|
||||||
{
|
|
||||||
fprintf(ofp, ",\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf(ofp, ", ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fprintf(ofp, "0x%02X};\n\n", buffer[n-1]);
|
|
||||||
}
|
|
||||||
fclose(ifp);
|
|
||||||
|
|
||||||
/* Provide a function to write the data to a file. */
|
|
||||||
fprintf(ofp, "extern %s_EXPORT int %sEncodedWriteArray%s(const char* fname)\n",
|
|
||||||
argv[3], argv[3], argv[4]);
|
|
||||||
fprintf(ofp, "{\n");
|
|
||||||
fprintf(ofp, " FILE* ofp = fopen(fname, \"wb\");\n");
|
|
||||||
fprintf(ofp, " if(!ofp) { return 0; }\n");
|
|
||||||
for(i=0; i < count; ++i)
|
|
||||||
{
|
|
||||||
fprintf(ofp, " if(fwrite(kwsysEncodedArray%s_%d, 1,\n"
|
|
||||||
" sizeof(kwsysEncodedArray%s_%d), ofp) !=\n"
|
|
||||||
" sizeof(kwsysEncodedArray%s_%d))\n",
|
|
||||||
argv[4], i, argv[4], i, argv[4], i);
|
|
||||||
fprintf(ofp, " {\n");
|
|
||||||
fprintf(ofp, " fclose(ofp);\n");
|
|
||||||
fprintf(ofp, " kwsys_unlink(fname);\n");
|
|
||||||
fprintf(ofp, " return 0;\n");
|
|
||||||
fprintf(ofp, " }\n");
|
|
||||||
}
|
|
||||||
fprintf(ofp, " fclose(ofp);\n");
|
|
||||||
fprintf(ofp, " return 1;\n");
|
|
||||||
fprintf(ofp, "}\n");
|
|
||||||
fclose(ofp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,211 +0,0 @@
|
||||||
/*============================================================================
|
|
||||||
KWSys - Kitware System Library
|
|
||||||
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
|
|
||||||
|
|
||||||
Distributed under the OSI-approved BSD License (the "License");
|
|
||||||
see accompanying file Copyright.txt for details.
|
|
||||||
|
|
||||||
This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
||||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
See the License for more information.
|
|
||||||
============================================================================*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
On Windows9x platforms, this executable is spawned between a parent
|
|
||||||
process and the child it is invoking to work around a bug. See the
|
|
||||||
Win32 implementation file for details.
|
|
||||||
|
|
||||||
Future Work: This executable must be linked statically against the C
|
|
||||||
runtime library before being encoded into the library. Building it
|
|
||||||
in this way may be hard because CMake has limited abilities to build
|
|
||||||
different targets with different configurations in the same
|
|
||||||
directory. We may just have to create and encode the executable
|
|
||||||
once instead of generating it during the build. This would be an
|
|
||||||
acceptable solution because the forwarding executable should not
|
|
||||||
change very often and is pretty simple.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning (push, 1)
|
|
||||||
#endif
|
|
||||||
#include <windows.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
void ReportLastError(HANDLE errorPipe);
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
/* Process startup information for the real child. */
|
|
||||||
STARTUPINFO si;
|
|
||||||
PROCESS_INFORMATION pi;
|
|
||||||
|
|
||||||
/* The result of waiting for the child to exit. */
|
|
||||||
DWORD waitResult;
|
|
||||||
|
|
||||||
/* The child's process return code. */
|
|
||||||
DWORD retVal;
|
|
||||||
|
|
||||||
/* The command line used to invoke this process. */
|
|
||||||
LPSTR commandLine = GetCommandLine();
|
|
||||||
|
|
||||||
/* Pointer that will be advanced to the beginning of the command
|
|
||||||
line of the real child process. */
|
|
||||||
LPSTR cmdLine = commandLine;
|
|
||||||
|
|
||||||
/* Handle to the error reporting pipe provided by the parent. This
|
|
||||||
is parsed off the command line. */
|
|
||||||
HANDLE errorPipe = 0;
|
|
||||||
HANDLE errorPipeOrig = 0;
|
|
||||||
|
|
||||||
/* Handle to the event the parent uses to tell us to resume the child.
|
|
||||||
This is parsed off the command line. */
|
|
||||||
HANDLE resumeEvent = 0;
|
|
||||||
|
|
||||||
/* Handle to the event the parent uses to tell us to kill the child.
|
|
||||||
This is parsed off the command line. */
|
|
||||||
HANDLE killEvent = 0;
|
|
||||||
|
|
||||||
/* Flag for whether to hide window of child process. */
|
|
||||||
int hideWindow = 0;
|
|
||||||
|
|
||||||
/* An array of the handles on which we wait when the child is
|
|
||||||
running. */
|
|
||||||
HANDLE waitHandles[2] = {0, 0};
|
|
||||||
|
|
||||||
/* Move the pointer past the name of this executable. */
|
|
||||||
if(*cmdLine == '"')
|
|
||||||
{
|
|
||||||
++cmdLine;
|
|
||||||
while(*cmdLine && *cmdLine != '"') { ++cmdLine; }
|
|
||||||
if(*cmdLine) { ++cmdLine; }
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse the error pipe handle. */
|
|
||||||
while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
|
|
||||||
sscanf(cmdLine, "%p", &errorPipeOrig);
|
|
||||||
|
|
||||||
/* Parse the resume event handle. */
|
|
||||||
while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
|
|
||||||
while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
|
|
||||||
sscanf(cmdLine, "%p", &resumeEvent);
|
|
||||||
|
|
||||||
/* Parse the kill event handle. */
|
|
||||||
while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
|
|
||||||
while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
|
|
||||||
sscanf(cmdLine, "%p", &killEvent);
|
|
||||||
|
|
||||||
/* Parse the hide window flag. */
|
|
||||||
while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
|
|
||||||
while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
|
|
||||||
sscanf(cmdLine, "%d", &hideWindow);
|
|
||||||
|
|
||||||
/* Skip to the beginning of the command line of the real child. */
|
|
||||||
while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
|
|
||||||
while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
|
|
||||||
|
|
||||||
/* Create a non-inherited copy of the error pipe. We do not want
|
|
||||||
the child to get it. */
|
|
||||||
if(DuplicateHandle(GetCurrentProcess(), errorPipeOrig,
|
|
||||||
GetCurrentProcess(), &errorPipe,
|
|
||||||
0, FALSE, DUPLICATE_SAME_ACCESS))
|
|
||||||
{
|
|
||||||
/* Have a non-inherited duplicate. Close the inherited one. */
|
|
||||||
CloseHandle(errorPipeOrig);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Could not duplicate handle. Report the error. */
|
|
||||||
ReportLastError(errorPipeOrig);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create the subprocess. */
|
|
||||||
ZeroMemory(&si, sizeof(si));
|
|
||||||
ZeroMemory(&pi, sizeof(pi));
|
|
||||||
si.cb = sizeof(si);
|
|
||||||
si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
|
|
||||||
si.wShowWindow = hideWindow?SW_HIDE:SW_SHOWDEFAULT;
|
|
||||||
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
|
||||||
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
||||||
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
|
||||||
if(CreateProcess(0, cmdLine, 0, 0, TRUE, CREATE_SUSPENDED, 0, 0, &si, &pi))
|
|
||||||
{
|
|
||||||
/* Process created successfully. Close the error reporting pipe
|
|
||||||
to notify the parent of success. */
|
|
||||||
CloseHandle(errorPipe);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Error creating the process. Report the error to the parent
|
|
||||||
process through the special error reporting pipe. */
|
|
||||||
ReportLastError(errorPipe);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait for resume or kill event from parent. */
|
|
||||||
waitHandles[0] = killEvent;
|
|
||||||
waitHandles[1] = resumeEvent;
|
|
||||||
waitResult = WaitForMultipleObjects(2, waitHandles, 0, INFINITE);
|
|
||||||
|
|
||||||
/* Check what happened. */
|
|
||||||
if(waitResult == WAIT_OBJECT_0)
|
|
||||||
{
|
|
||||||
/* We were asked to kill the child. */
|
|
||||||
TerminateProcess(pi.hProcess, 255);
|
|
||||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
|
||||||
CloseHandle(pi.hProcess);
|
|
||||||
CloseHandle(pi.hThread);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* We were asked to resume the child. */
|
|
||||||
ResumeThread(pi.hThread);
|
|
||||||
CloseHandle(pi.hThread);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait for subprocess to exit or for kill event from parent. */
|
|
||||||
waitHandles[0] = killEvent;
|
|
||||||
waitHandles[1] = pi.hProcess;
|
|
||||||
waitResult = WaitForMultipleObjects(2, waitHandles, 0, INFINITE);
|
|
||||||
|
|
||||||
/* Check what happened. */
|
|
||||||
if(waitResult == WAIT_OBJECT_0)
|
|
||||||
{
|
|
||||||
/* We were asked to kill the child. */
|
|
||||||
TerminateProcess(pi.hProcess, 255);
|
|
||||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
|
||||||
CloseHandle(pi.hProcess);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* The child exited. Get the return code. */
|
|
||||||
GetExitCodeProcess(pi.hProcess, &retVal);
|
|
||||||
CloseHandle(pi.hProcess);
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReportLastError(HANDLE errorPipe)
|
|
||||||
{
|
|
||||||
LPVOID lpMsgBuf;
|
|
||||||
DWORD n;
|
|
||||||
FormatMessage(
|
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
||||||
NULL,
|
|
||||||
GetLastError(),
|
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
|
||||||
(LPTSTR) &lpMsgBuf,
|
|
||||||
0,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
WriteFile(errorPipe, lpMsgBuf, strlen(lpMsgBuf)+1, &n, 0);
|
|
||||||
LocalFree( lpMsgBuf );
|
|
||||||
}
|
|
|
@ -28,14 +28,6 @@ On windows, a thread is created to wait for data on each pipe. The
|
||||||
threads are synchronized with the main thread to simulate the use of
|
threads are synchronized with the main thread to simulate the use of
|
||||||
a UNIX-style select system call.
|
a UNIX-style select system call.
|
||||||
|
|
||||||
On Windows9x platforms, a small WIN32 console application is spawned
|
|
||||||
in-between the calling process and the actual child to be executed.
|
|
||||||
This is to work-around a problem with connecting pipes from WIN16
|
|
||||||
console applications to WIN32 applications.
|
|
||||||
|
|
||||||
For more information, please check Microsoft Knowledge Base Articles
|
|
||||||
Q190351 and Q150956.
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
@ -91,18 +83,12 @@ Q190351 and Q150956.
|
||||||
# define KWSYSPE_DEBUG(x) (void)1
|
# define KWSYSPE_DEBUG(x) (void)1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define kwsysEncodedWriteArrayProcessFwd9x kwsys_ns(EncodedWriteArrayProcessFwd9x)
|
|
||||||
|
|
||||||
typedef LARGE_INTEGER kwsysProcessTime;
|
typedef LARGE_INTEGER kwsysProcessTime;
|
||||||
|
|
||||||
typedef struct kwsysProcessCreateInformation_s
|
typedef struct kwsysProcessCreateInformation_s
|
||||||
{
|
{
|
||||||
/* Windows child startup control data. */
|
/* Windows child startup control data. */
|
||||||
STARTUPINFO StartupInfo;
|
STARTUPINFO StartupInfo;
|
||||||
|
|
||||||
/* Special error reporting pipe for Win9x forwarding executable. */
|
|
||||||
HANDLE ErrorPipeRead;
|
|
||||||
HANDLE ErrorPipeWrite;
|
|
||||||
} kwsysProcessCreateInformation;
|
} kwsysProcessCreateInformation;
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
@ -146,7 +132,6 @@ static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProc
|
||||||
static void kwsysProcessSetExitException(kwsysProcess* cp, int code);
|
static void kwsysProcessSetExitException(kwsysProcess* cp, int code);
|
||||||
static void kwsysProcessKillTree(int pid);
|
static void kwsysProcessKillTree(int pid);
|
||||||
static void kwsysProcessDisablePipeThreads(kwsysProcess* cp);
|
static void kwsysProcessDisablePipeThreads(kwsysProcess* cp);
|
||||||
extern kwsysEXPORT int kwsysEncodedWriteArrayProcessFwd9x(const char* fname);
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
/* A structure containing synchronization data for each thread. */
|
/* A structure containing synchronization data for each thread. */
|
||||||
|
@ -233,15 +218,6 @@ struct kwsysProcess_s
|
||||||
/* Whether to treat command lines as verbatim. */
|
/* Whether to treat command lines as verbatim. */
|
||||||
int Verbatim;
|
int Verbatim;
|
||||||
|
|
||||||
/* On Win9x platforms, the path to the forwarding executable. */
|
|
||||||
char* Win9x;
|
|
||||||
|
|
||||||
/* On Win9x platforms, the resume event for the forwarding executable. */
|
|
||||||
HANDLE Win9xResumeEvent;
|
|
||||||
|
|
||||||
/* On Win9x platforms, the kill event for the forwarding executable. */
|
|
||||||
HANDLE Win9xKillEvent;
|
|
||||||
|
|
||||||
/* Mutex to protect the shared index used by threads to report data. */
|
/* Mutex to protect the shared index used by threads to report data. */
|
||||||
HANDLE SharedIndexMutex;
|
HANDLE SharedIndexMutex;
|
||||||
|
|
||||||
|
@ -269,9 +245,6 @@ struct kwsysProcess_s
|
||||||
HANDLE PipeNativeSTDOUT[2];
|
HANDLE PipeNativeSTDOUT[2];
|
||||||
HANDLE PipeNativeSTDERR[2];
|
HANDLE PipeNativeSTDERR[2];
|
||||||
|
|
||||||
/* Handle to automatically delete the Win9x forwarding executable. */
|
|
||||||
HANDLE Win9xHandle;
|
|
||||||
|
|
||||||
/* ------------- Data managed per call to Execute ------------- */
|
/* ------------- Data managed per call to Execute ------------- */
|
||||||
|
|
||||||
/* The exceptional behavior that terminated the process, if any. */
|
/* The exceptional behavior that terminated the process, if any. */
|
||||||
|
@ -311,7 +284,7 @@ struct kwsysProcess_s
|
||||||
for pipes to close after process termination. */
|
for pipes to close after process termination. */
|
||||||
int PipesLeft;
|
int PipesLeft;
|
||||||
|
|
||||||
/* Buffer for error messages (possibly from Win9x child). */
|
/* Buffer for error messages. */
|
||||||
char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1];
|
char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1];
|
||||||
|
|
||||||
/* Description for the ExitException. */
|
/* Description for the ExitException. */
|
||||||
|
@ -337,9 +310,6 @@ kwsysProcess* kwsysProcess_New(void)
|
||||||
/* Process control structure. */
|
/* Process control structure. */
|
||||||
kwsysProcess* cp;
|
kwsysProcess* cp;
|
||||||
|
|
||||||
/* Path to Win9x forwarding executable. */
|
|
||||||
char* win9x = 0;
|
|
||||||
|
|
||||||
/* Windows version number data. */
|
/* Windows version number data. */
|
||||||
OSVERSIONINFO osv;
|
OSVERSIONINFO osv;
|
||||||
|
|
||||||
|
@ -365,73 +335,11 @@ kwsysProcess* kwsysProcess_New(void)
|
||||||
GetVersionEx(&osv);
|
GetVersionEx(&osv);
|
||||||
if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
|
if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
|
||||||
{
|
{
|
||||||
/* This is Win9x. We need the console forwarding executable to
|
/* Win9x no longer supported. */
|
||||||
work-around a Windows 9x bug. */
|
|
||||||
char fwdName[_MAX_FNAME+1] = "";
|
|
||||||
char tempDir[_MAX_PATH+1] = "";
|
|
||||||
|
|
||||||
/* We will try putting the executable in the system temp
|
|
||||||
directory. Note that the returned path already has a trailing
|
|
||||||
slash. */
|
|
||||||
DWORD length = GetTempPath(_MAX_PATH+1, tempDir);
|
|
||||||
|
|
||||||
/* Construct the executable name from the process id and kwsysProcess
|
|
||||||
instance. This should be unique. */
|
|
||||||
sprintf(fwdName, KWSYS_NAMESPACE_STRING "pew9xfwd_%ld_%p.exe",
|
|
||||||
GetCurrentProcessId(), cp);
|
|
||||||
|
|
||||||
/* If we have a temp directory, use it. */
|
|
||||||
if(length > 0 && length <= _MAX_PATH)
|
|
||||||
{
|
|
||||||
/* Allocate a buffer to hold the forwarding executable path. */
|
|
||||||
size_t tdlen = strlen(tempDir);
|
|
||||||
win9x = (char*)malloc(tdlen + strlen(fwdName) + 2);
|
|
||||||
if(!win9x)
|
|
||||||
{
|
|
||||||
kwsysProcess_Delete(cp);
|
kwsysProcess_Delete(cp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Construct the full path to the forwarding executable. */
|
|
||||||
sprintf(win9x, "%s%s", tempDir, fwdName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we found a place to put the forwarding executable, try to
|
|
||||||
write it. */
|
|
||||||
if(win9x)
|
|
||||||
{
|
|
||||||
if(!kwsysEncodedWriteArrayProcessFwd9x(win9x))
|
|
||||||
{
|
|
||||||
/* Failed to create forwarding executable. Give up. */
|
|
||||||
free(win9x);
|
|
||||||
kwsysProcess_Delete(cp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a handle to the file that will delete it when closed. */
|
|
||||||
cp->Win9xHandle = CreateFile(win9x, GENERIC_READ, FILE_SHARE_READ, 0,
|
|
||||||
OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);
|
|
||||||
if(cp->Win9xHandle == INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
/* We were not able to get a read handle for the forwarding
|
|
||||||
executable. It will not be deleted properly. Give up. */
|
|
||||||
_unlink(win9x);
|
|
||||||
free(win9x);
|
|
||||||
kwsysProcess_Delete(cp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Failed to find a place to put forwarding executable. */
|
|
||||||
kwsysProcess_Delete(cp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Save the path to the forwarding executable. */
|
|
||||||
cp->Win9x = win9x;
|
|
||||||
|
|
||||||
/* Initially no thread owns the mutex. Initialize semaphore to 1. */
|
/* Initially no thread owns the mutex. Initialize semaphore to 1. */
|
||||||
if(!(cp->SharedIndexMutex = CreateSemaphore(0, 1, 1, 0)))
|
if(!(cp->SharedIndexMutex = CreateSemaphore(0, 1, 1, 0)))
|
||||||
{
|
{
|
||||||
|
@ -446,30 +354,6 @@ kwsysProcess* kwsysProcess_New(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cp->Win9x)
|
|
||||||
{
|
|
||||||
SECURITY_ATTRIBUTES sa;
|
|
||||||
ZeroMemory(&sa, sizeof(sa));
|
|
||||||
sa.nLength = sizeof(sa);
|
|
||||||
sa.bInheritHandle = TRUE;
|
|
||||||
|
|
||||||
/* Create an event to tell the forwarding executable to resume the
|
|
||||||
child. */
|
|
||||||
if(!(cp->Win9xResumeEvent = CreateEvent(&sa, TRUE, 0, 0)))
|
|
||||||
{
|
|
||||||
kwsysProcess_Delete(cp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create an event to tell the forwarding executable to kill the
|
|
||||||
child. */
|
|
||||||
if(!(cp->Win9xKillEvent = CreateEvent(&sa, TRUE, 0, 0)))
|
|
||||||
{
|
|
||||||
kwsysProcess_Delete(cp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create the thread to read each pipe. */
|
/* Create the thread to read each pipe. */
|
||||||
for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
|
for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
|
||||||
{
|
{
|
||||||
|
@ -620,13 +504,6 @@ void kwsysProcess_Delete(kwsysProcess* cp)
|
||||||
kwsysProcessCleanupHandle(&cp->SharedIndexMutex);
|
kwsysProcessCleanupHandle(&cp->SharedIndexMutex);
|
||||||
kwsysProcessCleanupHandle(&cp->Full);
|
kwsysProcessCleanupHandle(&cp->Full);
|
||||||
|
|
||||||
/* Close the Win9x resume and kill event handles. */
|
|
||||||
if(cp->Win9x)
|
|
||||||
{
|
|
||||||
kwsysProcessCleanupHandle(&cp->Win9xResumeEvent);
|
|
||||||
kwsysProcessCleanupHandle(&cp->Win9xKillEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free memory. */
|
/* Free memory. */
|
||||||
kwsysProcess_SetCommand(cp, 0);
|
kwsysProcess_SetCommand(cp, 0);
|
||||||
kwsysProcess_SetWorkingDirectory(cp, 0);
|
kwsysProcess_SetWorkingDirectory(cp, 0);
|
||||||
|
@ -637,12 +514,6 @@ void kwsysProcess_Delete(kwsysProcess* cp)
|
||||||
{
|
{
|
||||||
free(cp->CommandExitCodes);
|
free(cp->CommandExitCodes);
|
||||||
}
|
}
|
||||||
if(cp->Win9x)
|
|
||||||
{
|
|
||||||
/* Close our handle to the forwarding executable file. This will
|
|
||||||
cause it to be deleted. */
|
|
||||||
kwsysProcessCleanupHandle(&cp->Win9xHandle);
|
|
||||||
}
|
|
||||||
free(cp);
|
free(cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1017,21 +888,6 @@ void kwsysProcess_Execute(kwsysProcess* cp)
|
||||||
SetCurrentDirectory(cp->WorkingDirectory);
|
SetCurrentDirectory(cp->WorkingDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the Win9x resume and kill events. */
|
|
||||||
if(cp->Win9x)
|
|
||||||
{
|
|
||||||
if(!ResetEvent(cp->Win9xResumeEvent))
|
|
||||||
{
|
|
||||||
kwsysProcessCleanup(cp, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(!ResetEvent(cp->Win9xKillEvent))
|
|
||||||
{
|
|
||||||
kwsysProcessCleanup(cp, 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize startup info data. */
|
/* Initialize startup info data. */
|
||||||
ZeroMemory(&si, sizeof(si));
|
ZeroMemory(&si, sizeof(si));
|
||||||
si.StartupInfo.cb = sizeof(si.StartupInfo);
|
si.StartupInfo.cb = sizeof(si.StartupInfo);
|
||||||
|
@ -1130,8 +986,6 @@ void kwsysProcess_Execute(kwsysProcess* cp)
|
||||||
STD_OUTPUT_HANDLE);
|
STD_OUTPUT_HANDLE);
|
||||||
kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError,
|
kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError,
|
||||||
STD_ERROR_HANDLE);
|
STD_ERROR_HANDLE);
|
||||||
kwsysProcessCleanupHandle(&si.ErrorPipeRead);
|
|
||||||
kwsysProcessCleanupHandle(&si.ErrorPipeWrite);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1160,17 +1014,10 @@ void kwsysProcess_Execute(kwsysProcess* cp)
|
||||||
|
|
||||||
/* All processes in the pipeline have been started in suspended
|
/* All processes in the pipeline have been started in suspended
|
||||||
mode. Resume them all now. */
|
mode. Resume them all now. */
|
||||||
if(cp->Win9x)
|
|
||||||
{
|
|
||||||
SetEvent(cp->Win9xResumeEvent);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for(i=0; i < cp->NumberOfCommands; ++i)
|
for(i=0; i < cp->NumberOfCommands; ++i)
|
||||||
{
|
{
|
||||||
ResumeThread(cp->ProcessInformation[i].hThread);
|
ResumeThread(cp->ProcessInformation[i].hThread);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- It is no longer safe to call kwsysProcessCleanup. ----- */
|
/* ---- It is no longer safe to call kwsysProcessCleanup. ----- */
|
||||||
/* Tell the pipe threads that a process has started. */
|
/* Tell the pipe threads that a process has started. */
|
||||||
|
@ -1480,14 +1327,6 @@ void kwsysProcess_Kill(kwsysProcess* cp)
|
||||||
|
|
||||||
/* Kill the children. */
|
/* Kill the children. */
|
||||||
cp->Killed = 1;
|
cp->Killed = 1;
|
||||||
if(cp->Win9x)
|
|
||||||
{
|
|
||||||
/* Windows 9x. Tell the forwarding executable to kill the child. */
|
|
||||||
SetEvent(cp->Win9xKillEvent);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Not Windows 9x. Just terminate the children. */
|
|
||||||
for(i=0; i < cp->NumberOfCommands; ++i)
|
for(i=0; i < cp->NumberOfCommands; ++i)
|
||||||
{
|
{
|
||||||
kwsysProcessKillTree(cp->ProcessInformation[i].dwProcessId);
|
kwsysProcessKillTree(cp->ProcessInformation[i].dwProcessId);
|
||||||
|
@ -1495,7 +1334,6 @@ void kwsysProcess_Kill(kwsysProcess* cp)
|
||||||
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread);
|
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread);
|
||||||
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess);
|
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* We are killing the children and ignoring all data. Do not wait
|
/* We are killing the children and ignoring all data. Do not wait
|
||||||
for them to exit. */
|
for them to exit. */
|
||||||
|
@ -1815,97 +1653,13 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the child process. */
|
|
||||||
{
|
|
||||||
BOOL r;
|
|
||||||
char* realCommand;
|
|
||||||
if(cp->Win9x)
|
|
||||||
{
|
|
||||||
/* Create an error reporting pipe for the forwarding executable.
|
|
||||||
Neither end is directly inherited. */
|
|
||||||
if(!CreatePipe(&si->ErrorPipeRead, &si->ErrorPipeWrite, 0, 0))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create an inherited duplicate of the write end. This also closes
|
|
||||||
the non-inherited version. */
|
|
||||||
if(!DuplicateHandle(GetCurrentProcess(), si->ErrorPipeWrite,
|
|
||||||
GetCurrentProcess(), &si->ErrorPipeWrite,
|
|
||||||
0, TRUE, (DUPLICATE_CLOSE_SOURCE |
|
|
||||||
DUPLICATE_SAME_ACCESS)))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The forwarding executable is given a handle to the error pipe
|
|
||||||
and resume and kill events. */
|
|
||||||
realCommand = (char*)malloc(strlen(cp->Win9x)+strlen(cp->Commands[index])+100);
|
|
||||||
if(!realCommand)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
sprintf(realCommand, "%s %p %p %p %d %s", cp->Win9x,
|
|
||||||
si->ErrorPipeWrite, cp->Win9xResumeEvent, cp->Win9xKillEvent,
|
|
||||||
cp->HideWindow, cp->Commands[index]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
realCommand = cp->Commands[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create the child in a suspended state so we can wait until all
|
/* Create the child in a suspended state so we can wait until all
|
||||||
children have been created before running any one. */
|
children have been created before running any one. */
|
||||||
r = CreateProcess(0, realCommand, 0, 0, TRUE,
|
if(!CreateProcess(0, cp->Commands[index], 0, 0, TRUE, CREATE_SUSPENDED, 0,
|
||||||
cp->Win9x? 0 : CREATE_SUSPENDED, 0, 0,
|
0, &si->StartupInfo, &cp->ProcessInformation[index]))
|
||||||
&si->StartupInfo, &cp->ProcessInformation[index]);
|
|
||||||
if(cp->Win9x)
|
|
||||||
{
|
|
||||||
/* Free memory. */
|
|
||||||
free(realCommand);
|
|
||||||
|
|
||||||
/* Close the error pipe write end so we can detect when the
|
|
||||||
forwarding executable closes it. */
|
|
||||||
kwsysProcessCleanupHandle(&si->ErrorPipeWrite);
|
|
||||||
if(r)
|
|
||||||
{
|
|
||||||
/* Wait for the forwarding executable to report an error or
|
|
||||||
close the error pipe to report success. */
|
|
||||||
DWORD total = 0;
|
|
||||||
DWORD n = 1;
|
|
||||||
while(total < KWSYSPE_PIPE_BUFFER_SIZE && n > 0)
|
|
||||||
{
|
|
||||||
if(ReadFile(si->ErrorPipeRead, cp->ErrorMessage+total,
|
|
||||||
KWSYSPE_PIPE_BUFFER_SIZE-total, &n, 0))
|
|
||||||
{
|
|
||||||
total += n;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
n = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(total > 0 || GetLastError() != ERROR_BROKEN_PIPE)
|
|
||||||
{
|
|
||||||
/* The forwarding executable could not run the process, or
|
|
||||||
there was an error reading from its error pipe. Preserve
|
|
||||||
the last error while cleaning up the forwarding executable
|
|
||||||
so the cleanup our caller does reports the proper error. */
|
|
||||||
DWORD error = GetLastError();
|
|
||||||
kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hThread);
|
|
||||||
kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hProcess);
|
|
||||||
SetLastError(error);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
kwsysProcessCleanupHandle(&si->ErrorPipeRead);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!r)
|
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Successfully created this child process. Close the current
|
/* Successfully created this child process. Close the current
|
||||||
process's copies of the inherited stdout and stdin handles. The
|
process's copies of the inherited stdout and stdin handles. The
|
||||||
|
@ -2151,12 +1905,6 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error)
|
||||||
|
|
||||||
/* Cleanup any processes already started in a suspended state. */
|
/* Cleanup any processes already started in a suspended state. */
|
||||||
if(cp->ProcessInformation)
|
if(cp->ProcessInformation)
|
||||||
{
|
|
||||||
if(cp->Win9x)
|
|
||||||
{
|
|
||||||
SetEvent(cp->Win9xKillEvent);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
for(i=0; i < cp->NumberOfCommands; ++i)
|
for(i=0; i < cp->NumberOfCommands; ++i)
|
||||||
{
|
{
|
||||||
|
@ -2166,7 +1914,6 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error)
|
||||||
WaitForSingleObject(cp->ProcessInformation[i].hProcess, INFINITE);
|
WaitForSingleObject(cp->ProcessInformation[i].hProcess, INFINITE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
for(i=0; i < cp->NumberOfCommands; ++i)
|
for(i=0; i < cp->NumberOfCommands; ++i)
|
||||||
{
|
{
|
||||||
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread);
|
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread);
|
||||||
|
|
|
@ -1,818 +0,0 @@
|
||||||
/*============================================================================
|
|
||||||
KWSys - Kitware System Library
|
|
||||||
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
|
|
||||||
|
|
||||||
Distributed under the OSI-approved BSD License (the "License");
|
|
||||||
see accompanying file Copyright.txt for details.
|
|
||||||
|
|
||||||
This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
||||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
See the License for more information.
|
|
||||||
============================================================================*/
|
|
||||||
#include "kwsysPrivate.h"
|
|
||||||
#include KWSYS_HEADER(Registry.hxx)
|
|
||||||
|
|
||||||
#include KWSYS_HEADER(Configure.hxx)
|
|
||||||
#include KWSYS_HEADER(ios/iostream)
|
|
||||||
#include KWSYS_HEADER(stl/string)
|
|
||||||
#include KWSYS_HEADER(stl/map)
|
|
||||||
#include KWSYS_HEADER(ios/iostream)
|
|
||||||
#include KWSYS_HEADER(ios/fstream)
|
|
||||||
#include KWSYS_HEADER(ios/sstream)
|
|
||||||
// Work-around CMake dependency scanning limitation. This must
|
|
||||||
// duplicate the above list of headers.
|
|
||||||
#if 0
|
|
||||||
# include "Registry.hxx.in"
|
|
||||||
# include "Configure.hxx.in"
|
|
||||||
# include "kwsys_stl.hxx.in"
|
|
||||||
# include "kwsys_stl_string.hxx.in"
|
|
||||||
# include "kwsys_stl_map.hxx.in"
|
|
||||||
# include "kwsys_ios_iostream.h.in"
|
|
||||||
# include "kwsys_ios_fstream.h.in"
|
|
||||||
# include "kwsys_ios_sstream.h.in"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <ctype.h> // for isspace
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h> /* strlen, strncpy */
|
|
||||||
#include <stdlib.h> /* getenv */
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
# include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
namespace KWSYS_NAMESPACE
|
|
||||||
{
|
|
||||||
class RegistryHelper {
|
|
||||||
public:
|
|
||||||
RegistryHelper(Registry::RegistryType registryType);
|
|
||||||
virtual ~RegistryHelper();
|
|
||||||
|
|
||||||
// Read a value from the registry.
|
|
||||||
virtual bool ReadValue(const char *key, const char **value);
|
|
||||||
|
|
||||||
// Delete a key from the registry.
|
|
||||||
virtual bool DeleteKey(const char *key);
|
|
||||||
|
|
||||||
// Delete a value from a given key.
|
|
||||||
virtual bool DeleteValue(const char *key);
|
|
||||||
|
|
||||||
// Set value in a given key.
|
|
||||||
virtual bool SetValue(const char *key, const char *value);
|
|
||||||
|
|
||||||
// Open the registry at toplevel/subkey.
|
|
||||||
virtual bool Open(const char *toplevel, const char *subkey,
|
|
||||||
int readonly);
|
|
||||||
|
|
||||||
// Close the registry.
|
|
||||||
virtual bool Close();
|
|
||||||
|
|
||||||
// Set the value of changed
|
|
||||||
void SetChanged(bool b) { m_Changed = b; }
|
|
||||||
void SetTopLevel(const char* tl);
|
|
||||||
const char* GetTopLevel() { return m_TopLevel.c_str(); }
|
|
||||||
|
|
||||||
//! Read from local or global scope. On Windows this mean from local machine
|
|
||||||
// or local user. On unix this will read from $HOME/.Projectrc or
|
|
||||||
// /etc/Project
|
|
||||||
void SetGlobalScope(bool b);
|
|
||||||
bool GetGlobalScope();
|
|
||||||
|
|
||||||
kwsys_stl::string EncodeKey(const char* str);
|
|
||||||
kwsys_stl::string EncodeValue(const char* str);
|
|
||||||
kwsys_stl::string DecodeValue(const char* str);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool m_Changed;
|
|
||||||
kwsys_stl::string m_TopLevel;
|
|
||||||
bool m_GlobalScope;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
HKEY HKey;
|
|
||||||
#endif
|
|
||||||
// Strip trailing and ending spaces.
|
|
||||||
char *Strip(char *str);
|
|
||||||
void SetSubKey(const char* sk);
|
|
||||||
kwsys_stl::string CreateKey(const char *key);
|
|
||||||
|
|
||||||
typedef kwsys_stl::map<kwsys_stl::string, kwsys_stl::string> StringToStringMap;
|
|
||||||
StringToStringMap EntriesMap;
|
|
||||||
kwsys_stl::string m_SubKey;
|
|
||||||
bool m_Empty;
|
|
||||||
bool m_SubKeySpecified;
|
|
||||||
kwsys_stl::string m_HomeDirectory;
|
|
||||||
|
|
||||||
Registry::RegistryType m_RegistryType;
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
#define Registry_BUFFER_SIZE 8192
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
Registry::Registry(Registry::RegistryType registryType)
|
|
||||||
{
|
|
||||||
m_Opened = false;
|
|
||||||
m_Locked = false;
|
|
||||||
this->Helper = 0;
|
|
||||||
this->Helper = new RegistryHelper(registryType);
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
Registry::~Registry()
|
|
||||||
{
|
|
||||||
if ( m_Opened )
|
|
||||||
{
|
|
||||||
kwsys_ios::cerr << "Registry::Close should be "
|
|
||||||
"called here. The registry is not closed."
|
|
||||||
<< kwsys_ios::endl;
|
|
||||||
}
|
|
||||||
delete this->Helper;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
void Registry::SetGlobalScope(bool b)
|
|
||||||
{
|
|
||||||
this->Helper->SetGlobalScope(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool Registry::GetGlobalScope()
|
|
||||||
{
|
|
||||||
return this->Helper->GetGlobalScope();
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool Registry::Open(const char *toplevel,
|
|
||||||
const char *subkey, int readonly)
|
|
||||||
{
|
|
||||||
bool res = false;
|
|
||||||
if ( m_Locked )
|
|
||||||
{
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
if ( m_Opened )
|
|
||||||
{
|
|
||||||
if ( !this->Close() )
|
|
||||||
{
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( !toplevel || !*toplevel )
|
|
||||||
{
|
|
||||||
kwsys_ios::cerr << "Registry::Opened() Toplevel not defined"
|
|
||||||
<< kwsys_ios::endl;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( isspace(toplevel[0]) ||
|
|
||||||
isspace(toplevel[strlen(toplevel)-1]) )
|
|
||||||
{
|
|
||||||
kwsys_ios::cerr << "Toplevel has to start with letter or number and end"
|
|
||||||
" with one" << kwsys_ios::endl;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = this->Helper->Open(toplevel, subkey, readonly);
|
|
||||||
if ( readonly != Registry::READONLY )
|
|
||||||
{
|
|
||||||
m_Locked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( res )
|
|
||||||
{
|
|
||||||
m_Opened = true;
|
|
||||||
this->Helper->SetTopLevel(toplevel);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool Registry::Close()
|
|
||||||
{
|
|
||||||
bool res = false;
|
|
||||||
if ( m_Opened )
|
|
||||||
{
|
|
||||||
res = this->Helper->Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( res )
|
|
||||||
{
|
|
||||||
m_Opened = false;
|
|
||||||
m_Locked = false;
|
|
||||||
this->Helper->SetChanged(false);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool Registry::ReadValue(const char *subkey,
|
|
||||||
const char *key,
|
|
||||||
const char **value)
|
|
||||||
{
|
|
||||||
bool res = false;
|
|
||||||
bool open = false;
|
|
||||||
if ( ! value )
|
|
||||||
{
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
*value = 0;
|
|
||||||
if ( !m_Opened )
|
|
||||||
{
|
|
||||||
if ( !this->Open(this->GetTopLevel(), subkey,
|
|
||||||
Registry::READONLY) )
|
|
||||||
{
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
open = true;
|
|
||||||
}
|
|
||||||
res = this->Helper->ReadValue(key, value);
|
|
||||||
|
|
||||||
if ( open )
|
|
||||||
{
|
|
||||||
if ( !this->Close() )
|
|
||||||
{
|
|
||||||
res = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool Registry::DeleteKey(const char *subkey, const char *key)
|
|
||||||
{
|
|
||||||
bool res = false;
|
|
||||||
bool open = false;
|
|
||||||
if ( !m_Opened )
|
|
||||||
{
|
|
||||||
if ( !this->Open(this->GetTopLevel(), subkey,
|
|
||||||
Registry::READWRITE) )
|
|
||||||
{
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
open = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = this->Helper->DeleteKey(key);
|
|
||||||
if ( res )
|
|
||||||
{
|
|
||||||
this->Helper->SetChanged(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( open )
|
|
||||||
{
|
|
||||||
if ( !this->Close() )
|
|
||||||
{
|
|
||||||
res = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool Registry::DeleteValue(const char *subkey, const char *key)
|
|
||||||
{
|
|
||||||
bool res = false;
|
|
||||||
bool open = false;
|
|
||||||
if ( !m_Opened )
|
|
||||||
{
|
|
||||||
if ( !this->Open(this->GetTopLevel(), subkey,
|
|
||||||
Registry::READWRITE) )
|
|
||||||
{
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
open = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = this->Helper->DeleteValue(key);
|
|
||||||
if ( res )
|
|
||||||
{
|
|
||||||
this->Helper->SetChanged(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( open )
|
|
||||||
{
|
|
||||||
if ( !this->Close() )
|
|
||||||
{
|
|
||||||
res = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool Registry::SetValue(const char *subkey, const char *key,
|
|
||||||
const char *value)
|
|
||||||
{
|
|
||||||
bool res = false;
|
|
||||||
bool open = false;
|
|
||||||
if ( !m_Opened )
|
|
||||||
{
|
|
||||||
if ( !this->Open(this->GetTopLevel(), subkey,
|
|
||||||
Registry::READWRITE) )
|
|
||||||
{
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
open = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = this->Helper->SetValue( key, value );
|
|
||||||
if ( res )
|
|
||||||
{
|
|
||||||
this->Helper->SetChanged(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( open )
|
|
||||||
{
|
|
||||||
if ( !this->Close() )
|
|
||||||
{
|
|
||||||
res = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
const char* Registry::GetTopLevel()
|
|
||||||
{
|
|
||||||
return this->Helper->GetTopLevel();
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
void Registry::SetTopLevel(const char* tl)
|
|
||||||
{
|
|
||||||
this->Helper->SetTopLevel(tl);
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
void RegistryHelper::SetTopLevel(const char* tl)
|
|
||||||
{
|
|
||||||
if ( tl )
|
|
||||||
{
|
|
||||||
m_TopLevel = tl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_TopLevel = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
RegistryHelper::RegistryHelper(Registry::RegistryType registryType)
|
|
||||||
{
|
|
||||||
m_Changed = false;
|
|
||||||
m_TopLevel = "";
|
|
||||||
m_SubKey = "";
|
|
||||||
m_SubKeySpecified = false;
|
|
||||||
m_Empty = true;
|
|
||||||
m_GlobalScope = false;
|
|
||||||
m_RegistryType = registryType;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
RegistryHelper::~RegistryHelper()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool RegistryHelper::Open(const char *toplevel, const char *subkey,
|
|
||||||
int readonly)
|
|
||||||
{
|
|
||||||
this->EntriesMap.clear();
|
|
||||||
m_Empty = 1;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
if ( m_RegistryType == Registry::WIN32_REGISTRY)
|
|
||||||
{
|
|
||||||
HKEY scope = HKEY_CURRENT_USER;
|
|
||||||
if ( this->GetGlobalScope() )
|
|
||||||
{
|
|
||||||
scope = HKEY_LOCAL_MACHINE;
|
|
||||||
}
|
|
||||||
int res = 0;
|
|
||||||
kwsys_ios::ostringstream str;
|
|
||||||
DWORD dwDummy;
|
|
||||||
str << "Software\\Kitware\\" << toplevel << "\\" << subkey;
|
|
||||||
if ( readonly == Registry::READONLY )
|
|
||||||
{
|
|
||||||
res = ( RegOpenKeyEx(scope, str.str().c_str(),
|
|
||||||
0, KEY_READ, &this->HKey) == ERROR_SUCCESS );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char lpClass[] = "";
|
|
||||||
res = ( RegCreateKeyEx(scope, str.str().c_str(),
|
|
||||||
0, lpClass, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE,
|
|
||||||
NULL, &this->HKey, &dwDummy) == ERROR_SUCCESS );
|
|
||||||
}
|
|
||||||
if ( res != 0 )
|
|
||||||
{
|
|
||||||
this->SetSubKey( subkey );
|
|
||||||
}
|
|
||||||
return (res != 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if ( m_RegistryType == Registry::FILE_REGISTRY )
|
|
||||||
{
|
|
||||||
bool res = false;
|
|
||||||
int cc;
|
|
||||||
kwsys_ios::ostringstream str;
|
|
||||||
const char* homeDirectory;
|
|
||||||
if ( (homeDirectory = getenv("HOME")) == 0 )
|
|
||||||
{
|
|
||||||
if ( (homeDirectory = getenv("USERPROFILE")) == 0 )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_HomeDirectory = homeDirectory;
|
|
||||||
str << m_HomeDirectory.c_str() << "/." << toplevel << "rc";
|
|
||||||
if ( readonly == Registry::READWRITE )
|
|
||||||
{
|
|
||||||
kwsys_ios::ofstream ofs( str.str().c_str(), kwsys_ios::ios::out|kwsys_ios::ios::app );
|
|
||||||
if ( ofs.fail() )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ofs.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
kwsys_ios::ifstream *ifs = new kwsys_ios::ifstream(str.str().c_str(), kwsys_ios::ios::in
|
|
||||||
#ifndef KWSYS_IOS_USE_ANSI
|
|
||||||
| kwsys_ios::ios::nocreate
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
if ( !ifs )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( ifs->fail())
|
|
||||||
{
|
|
||||||
delete ifs;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = true;
|
|
||||||
char buffer[Registry_BUFFER_SIZE];
|
|
||||||
while( !ifs->fail() )
|
|
||||||
{
|
|
||||||
ifs->getline(buffer, Registry_BUFFER_SIZE);
|
|
||||||
if ( ifs->fail() || ifs->eof() )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
char *line = this->Strip(buffer);
|
|
||||||
if ( *line == '#' || *line == 0 )
|
|
||||||
{
|
|
||||||
// Comment
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int linelen = static_cast<int>(strlen(line));
|
|
||||||
for ( cc = 0; cc < linelen; cc++ )
|
|
||||||
{
|
|
||||||
if ( line[cc] == '=' )
|
|
||||||
{
|
|
||||||
char *key = new char[ cc+1 ];
|
|
||||||
strncpy( key, line, cc );
|
|
||||||
key[cc] = 0;
|
|
||||||
char *value = line + cc + 1;
|
|
||||||
char *nkey = this->Strip(key);
|
|
||||||
char *nvalue = this->Strip(value);
|
|
||||||
this->EntriesMap[nkey] = this->DecodeValue(nvalue);
|
|
||||||
m_Empty = 0;
|
|
||||||
delete [] key;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ifs->close();
|
|
||||||
this->SetSubKey( subkey );
|
|
||||||
delete ifs;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool RegistryHelper::Close()
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
if ( m_RegistryType == Registry::WIN32_REGISTRY)
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
res = ( RegCloseKey(this->HKey) == ERROR_SUCCESS );
|
|
||||||
return (res != 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if ( m_RegistryType == Registry::FILE_REGISTRY )
|
|
||||||
{
|
|
||||||
if ( !m_Changed )
|
|
||||||
{
|
|
||||||
this->SetSubKey(0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
kwsys_ios::ostringstream str;
|
|
||||||
str << m_HomeDirectory.c_str() << "/." << this->GetTopLevel() << "rc";
|
|
||||||
kwsys_ios::ofstream *ofs = new kwsys_ios::ofstream(str.str().c_str(), kwsys_ios::ios::out);
|
|
||||||
if ( !ofs )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( ofs->fail())
|
|
||||||
{
|
|
||||||
delete ofs;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*ofs << "# This file is automatically generated by the application" << kwsys_ios::endl
|
|
||||||
<< "# If you change any lines or add new lines, note that all" << kwsys_ios::endl
|
|
||||||
<< "# comments and empty lines will be deleted. Every line has" << kwsys_ios::endl
|
|
||||||
<< "# to be in format: " << kwsys_ios::endl
|
|
||||||
<< "# key = value" << kwsys_ios::endl
|
|
||||||
<< "#" << kwsys_ios::endl;
|
|
||||||
|
|
||||||
if ( !this->EntriesMap.empty() )
|
|
||||||
{
|
|
||||||
RegistryHelper::StringToStringMap::iterator it;
|
|
||||||
for ( it = this->EntriesMap.begin();
|
|
||||||
it != this->EntriesMap.end();
|
|
||||||
++ it )
|
|
||||||
{
|
|
||||||
*ofs << it->first.c_str() << " = " << this->EncodeValue(it->second.c_str()).c_str() << kwsys_ios::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this->EntriesMap.clear();
|
|
||||||
ofs->close();
|
|
||||||
delete ofs;
|
|
||||||
this->SetSubKey(0);
|
|
||||||
m_Empty = 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool RegistryHelper::ReadValue(const char *skey, const char **value)
|
|
||||||
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
if ( m_RegistryType == Registry::WIN32_REGISTRY)
|
|
||||||
{
|
|
||||||
kwsys_stl::string key = this->CreateKey( skey );
|
|
||||||
if ( key.empty() )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
DWORD dwType, dwSize;
|
|
||||||
dwType = REG_SZ;
|
|
||||||
char buffer[1024]; // Replace with RegQueryInfoKey
|
|
||||||
dwSize = sizeof(buffer);
|
|
||||||
int res = ( RegQueryValueEx(this->HKey, skey, NULL, &dwType,
|
|
||||||
(BYTE *)buffer, &dwSize) == ERROR_SUCCESS );
|
|
||||||
if ( !res )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
this->EntriesMap[key] = buffer;
|
|
||||||
RegistryHelper::StringToStringMap::iterator it
|
|
||||||
= this->EntriesMap.find(key);
|
|
||||||
*value = it->second.c_str();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if ( m_RegistryType == Registry::FILE_REGISTRY )
|
|
||||||
{
|
|
||||||
bool res = false;
|
|
||||||
kwsys_stl::string key = this->CreateKey( skey );
|
|
||||||
if ( key.empty() )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
RegistryHelper::StringToStringMap::iterator it
|
|
||||||
= this->EntriesMap.find(key);
|
|
||||||
if ( it != this->EntriesMap.end() )
|
|
||||||
{
|
|
||||||
*value = it->second.c_str();
|
|
||||||
res = true;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool RegistryHelper::DeleteKey(const char* skey)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
if ( m_RegistryType == Registry::WIN32_REGISTRY)
|
|
||||||
{
|
|
||||||
int res = ( RegDeleteKey( this->HKey, skey ) == ERROR_SUCCESS );
|
|
||||||
return (res != 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if ( m_RegistryType == Registry::FILE_REGISTRY )
|
|
||||||
{
|
|
||||||
kwsys_stl::string key = this->CreateKey( skey );
|
|
||||||
if ( key.empty() )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
this->EntriesMap.erase(key);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool RegistryHelper::DeleteValue(const char *skey)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
if ( m_RegistryType == Registry::WIN32_REGISTRY)
|
|
||||||
{
|
|
||||||
int res = ( RegDeleteValue( this->HKey, skey ) == ERROR_SUCCESS );
|
|
||||||
return (res != 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if ( m_RegistryType == Registry::FILE_REGISTRY )
|
|
||||||
{
|
|
||||||
kwsys_stl::string key = this->CreateKey( skey );
|
|
||||||
if ( key.empty() )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
this->EntriesMap.erase(key);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool RegistryHelper::SetValue(const char *skey, const char *value)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
if ( m_RegistryType == Registry::WIN32_REGISTRY)
|
|
||||||
{
|
|
||||||
DWORD len = (DWORD)(value ? strlen(value) : 0);
|
|
||||||
int res = ( RegSetValueEx(this->HKey, skey, 0, REG_SZ,
|
|
||||||
(CONST BYTE *)(const char *)value,
|
|
||||||
len+1) == ERROR_SUCCESS );
|
|
||||||
return (res != 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if ( m_RegistryType == Registry::FILE_REGISTRY )
|
|
||||||
{
|
|
||||||
kwsys_stl::string key = this->CreateKey( skey );
|
|
||||||
if ( key.empty() )
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
this->EntriesMap[key] = value;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
kwsys_stl::string RegistryHelper::CreateKey( const char *key )
|
|
||||||
{
|
|
||||||
if ( !m_SubKeySpecified || m_SubKey.empty() || !key )
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
kwsys_ios::ostringstream ostr;
|
|
||||||
ostr << this->EncodeKey(this->m_SubKey.c_str()).c_str()
|
|
||||||
<< "\\" << this->EncodeKey(key).c_str();
|
|
||||||
return ostr.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
void RegistryHelper::SetSubKey(const char* sk)
|
|
||||||
{
|
|
||||||
if ( !sk )
|
|
||||||
{
|
|
||||||
m_SubKey = "";
|
|
||||||
m_SubKeySpecified = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_SubKey = sk;
|
|
||||||
m_SubKeySpecified = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
char *RegistryHelper::Strip(char *str)
|
|
||||||
{
|
|
||||||
int cc;
|
|
||||||
size_t len;
|
|
||||||
char *nstr;
|
|
||||||
if ( !str )
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
len = strlen(str);
|
|
||||||
nstr = str;
|
|
||||||
for( cc=0; cc < static_cast<int>(len); cc++ )
|
|
||||||
{
|
|
||||||
if ( !isspace( *nstr ) )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
nstr ++;
|
|
||||||
}
|
|
||||||
for( cc= static_cast<int>(strlen(nstr))-1; cc>=0; cc-- )
|
|
||||||
{
|
|
||||||
if ( !isspace( nstr[cc] ) )
|
|
||||||
{
|
|
||||||
nstr[cc+1] = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nstr;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
void RegistryHelper::SetGlobalScope(bool b)
|
|
||||||
{
|
|
||||||
m_GlobalScope = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
bool RegistryHelper::GetGlobalScope()
|
|
||||||
{
|
|
||||||
return m_GlobalScope;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
kwsys_stl::string RegistryHelper::EncodeKey(const char* str)
|
|
||||||
{
|
|
||||||
kwsys_ios::ostringstream ostr;
|
|
||||||
while ( *str )
|
|
||||||
{
|
|
||||||
switch ( *str )
|
|
||||||
{
|
|
||||||
case '%': case '=': case '\n': case '\r': case '\t':
|
|
||||||
char buffer[4];
|
|
||||||
sprintf(buffer, "%%%02X", *str);
|
|
||||||
ostr << buffer;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ostr << *str;
|
|
||||||
}
|
|
||||||
str ++;
|
|
||||||
}
|
|
||||||
return ostr.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
kwsys_stl::string RegistryHelper::EncodeValue(const char* str)
|
|
||||||
{
|
|
||||||
kwsys_ios::ostringstream ostr;
|
|
||||||
while ( *str )
|
|
||||||
{
|
|
||||||
switch ( *str )
|
|
||||||
{
|
|
||||||
case '%': case '=': case '\n': case '\r': case '\t':
|
|
||||||
char buffer[4];
|
|
||||||
sprintf(buffer, "%%%02X", *str);
|
|
||||||
ostr << buffer;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ostr << *str;
|
|
||||||
}
|
|
||||||
str ++;
|
|
||||||
}
|
|
||||||
return ostr.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
kwsys_stl::string RegistryHelper::DecodeValue(const char* str)
|
|
||||||
{
|
|
||||||
kwsys_ios::ostringstream ostr;
|
|
||||||
while ( *str )
|
|
||||||
{
|
|
||||||
unsigned int val;
|
|
||||||
switch ( *str )
|
|
||||||
{
|
|
||||||
case '%':
|
|
||||||
if ( *(str+1) && *(str+2) && sscanf(str+1, "%x", &val) == 1 )
|
|
||||||
{
|
|
||||||
ostr << static_cast<char>(val);
|
|
||||||
str += 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ostr << *str;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ostr << *str;
|
|
||||||
}
|
|
||||||
str ++;
|
|
||||||
}
|
|
||||||
return ostr.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace KWSYS_NAMESPACE
|
|
|
@ -1,107 +0,0 @@
|
||||||
/*============================================================================
|
|
||||||
KWSys - Kitware System Library
|
|
||||||
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
|
|
||||||
|
|
||||||
Distributed under the OSI-approved BSD License (the "License");
|
|
||||||
see accompanying file Copyright.txt for details.
|
|
||||||
|
|
||||||
This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
||||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
See the License for more information.
|
|
||||||
============================================================================*/
|
|
||||||
#ifndef @KWSYS_NAMESPACE@_Registry_hxx
|
|
||||||
#define @KWSYS_NAMESPACE@_Registry_hxx
|
|
||||||
|
|
||||||
#include <@KWSYS_NAMESPACE@/Configure.h>
|
|
||||||
|
|
||||||
#include <@KWSYS_NAMESPACE@/stl/string>
|
|
||||||
|
|
||||||
namespace @KWSYS_NAMESPACE@
|
|
||||||
{
|
|
||||||
|
|
||||||
class RegistryHelper;
|
|
||||||
|
|
||||||
/** \class Registry
|
|
||||||
* \brief Portable registry class
|
|
||||||
*
|
|
||||||
* This class abstracts the storing of data that can be restored
|
|
||||||
* when the program executes again. On Win32 platform it is
|
|
||||||
* implemented using the registry and on unix as a file in
|
|
||||||
* the user's home directory.
|
|
||||||
*/
|
|
||||||
class @KWSYS_NAMESPACE@_EXPORT Registry
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum RegistryType
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
WIN32_REGISTRY,
|
|
||||||
#endif
|
|
||||||
FILE_REGISTRY
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
Registry(RegistryType registryType = WIN32_REGISTRY);
|
|
||||||
#else
|
|
||||||
Registry(RegistryType registryType = FILE_REGISTRY);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
virtual ~Registry();
|
|
||||||
|
|
||||||
//! Read a value from the registry.
|
|
||||||
bool ReadValue(const char *subkey, const char *key, const char **value);
|
|
||||||
|
|
||||||
//! Delete a key from the registry.
|
|
||||||
bool DeleteKey(const char *subkey, const char *key);
|
|
||||||
|
|
||||||
//! Delete a value from a given key.
|
|
||||||
bool DeleteValue(const char *subkey, const char *key);
|
|
||||||
|
|
||||||
//! Set value in a given key.
|
|
||||||
bool SetValue(const char *subkey, const char *key,
|
|
||||||
const char *value);
|
|
||||||
|
|
||||||
//! Open the registry at toplevel/subkey.
|
|
||||||
bool Open(const char *toplevel, const char *subkey,
|
|
||||||
int readonly);
|
|
||||||
|
|
||||||
//! Close the registry.
|
|
||||||
bool Close();
|
|
||||||
|
|
||||||
//! Read from local or global scope. On Windows this mean from local machine
|
|
||||||
// or local user. On unix this will read from $HOME/.Projectrc or
|
|
||||||
// /etc/Project
|
|
||||||
void GlobalScopeOn() { this->SetGlobalScope(1); }
|
|
||||||
void GlobalScopeOff() { this->SetGlobalScope(0); }
|
|
||||||
void SetGlobalScope(bool b);
|
|
||||||
bool GetGlobalScope();
|
|
||||||
|
|
||||||
// Set or get the toplevel registry key.
|
|
||||||
void SetTopLevel(const char* tl);
|
|
||||||
const char* GetTopLevel();
|
|
||||||
|
|
||||||
// Return true if registry opened
|
|
||||||
bool GetOpened() { return m_Opened; }
|
|
||||||
|
|
||||||
// Should the registry be locked?
|
|
||||||
bool GetLocked() { return m_Locked; }
|
|
||||||
|
|
||||||
enum {
|
|
||||||
READONLY,
|
|
||||||
READWRITE
|
|
||||||
};
|
|
||||||
|
|
||||||
// Return true if the character is space.
|
|
||||||
int IsSpace(char c);
|
|
||||||
|
|
||||||
private:
|
|
||||||
RegistryHelper* Helper;
|
|
||||||
|
|
||||||
bool m_Opened;
|
|
||||||
|
|
||||||
bool m_Locked;
|
|
||||||
}; // End Class: Registry
|
|
||||||
|
|
||||||
} // namespace @KWSYS_NAMESPACE@
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -307,7 +307,7 @@ public:
|
||||||
enum Manufacturer
|
enum Manufacturer
|
||||||
{
|
{
|
||||||
AMD, Intel, NSC, UMC, Cyrix, NexGen, IDT, Rise, Transmeta, Sun, IBM,
|
AMD, Intel, NSC, UMC, Cyrix, NexGen, IDT, Rise, Transmeta, Sun, IBM,
|
||||||
Motorola, UnknownManufacturer
|
Motorola, HP, UnknownManufacturer
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -346,7 +346,7 @@ protected:
|
||||||
static void Delay (unsigned int);
|
static void Delay (unsigned int);
|
||||||
static void DelayOverhead (unsigned int);
|
static void DelayOverhead (unsigned int);
|
||||||
|
|
||||||
void FindManufacturer();
|
void FindManufacturer(const kwsys_stl::string &family = "");
|
||||||
|
|
||||||
// For Mac
|
// For Mac
|
||||||
bool ParseSysCtl();
|
bool ParseSysCtl();
|
||||||
|
@ -1144,6 +1144,7 @@ void SystemInformationImplementation::RunCPUCheck()
|
||||||
{
|
{
|
||||||
// Retrieve the CPU details.
|
// Retrieve the CPU details.
|
||||||
RetrieveCPUIdentity();
|
RetrieveCPUIdentity();
|
||||||
|
this->FindManufacturer();
|
||||||
RetrieveCPUFeatures();
|
RetrieveCPUFeatures();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1415,6 +1416,8 @@ const char * SystemInformationImplementation::GetVendorID()
|
||||||
return "IBM";
|
return "IBM";
|
||||||
case Motorola:
|
case Motorola:
|
||||||
return "Motorola";
|
return "Motorola";
|
||||||
|
case HP:
|
||||||
|
return "Hewlett-Packard";
|
||||||
default:
|
default:
|
||||||
return "Unknown Manufacturer";
|
return "Unknown Manufacturer";
|
||||||
}
|
}
|
||||||
|
@ -1670,7 +1673,7 @@ bool SystemInformationImplementation::RetrieveCPUFeatures()
|
||||||
#endif
|
#endif
|
||||||
; <<CPUID>>
|
; <<CPUID>>
|
||||||
; eax = 1 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision
|
; eax = 1 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision
|
||||||
; ebx: 31..24 - default APIC ID, 23..16 - logical processsor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID
|
; ebx: 31..24 - default APIC ID, 23..16 - logical processor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID
|
||||||
; edx: CPU feature flags
|
; edx: CPU feature flags
|
||||||
mov eax,1
|
mov eax,1
|
||||||
CPUID_INSTRUCTION
|
CPUID_INSTRUCTION
|
||||||
|
@ -1755,7 +1758,7 @@ bool SystemInformationImplementation::RetrieveCPUFeatures()
|
||||||
|
|
||||||
|
|
||||||
/** Find the manufacturer given the vendor id */
|
/** Find the manufacturer given the vendor id */
|
||||||
void SystemInformationImplementation::FindManufacturer()
|
void SystemInformationImplementation::FindManufacturer(const kwsys_stl::string& family)
|
||||||
{
|
{
|
||||||
if (this->ChipID.Vendor == "GenuineIntel") this->ChipManufacturer = Intel; // Intel Corp.
|
if (this->ChipID.Vendor == "GenuineIntel") this->ChipManufacturer = Intel; // Intel Corp.
|
||||||
else if (this->ChipID.Vendor == "UMC UMC UMC ") this->ChipManufacturer = UMC; // United Microelectronics Corp.
|
else if (this->ChipID.Vendor == "UMC UMC UMC ") this->ChipManufacturer = UMC; // United Microelectronics Corp.
|
||||||
|
@ -1771,6 +1774,7 @@ void SystemInformationImplementation::FindManufacturer()
|
||||||
else if (this->ChipID.Vendor == "Sun") this->ChipManufacturer = Sun; // Sun Microelectronics
|
else if (this->ChipID.Vendor == "Sun") this->ChipManufacturer = Sun; // Sun Microelectronics
|
||||||
else if (this->ChipID.Vendor == "IBM") this->ChipManufacturer = IBM; // IBM Microelectronics
|
else if (this->ChipID.Vendor == "IBM") this->ChipManufacturer = IBM; // IBM Microelectronics
|
||||||
else if (this->ChipID.Vendor == "Motorola") this->ChipManufacturer = Motorola; // Motorola Microelectronics
|
else if (this->ChipID.Vendor == "Motorola") this->ChipManufacturer = Motorola; // Motorola Microelectronics
|
||||||
|
else if (family.substr(0, 7) == "PA-RISC") this->ChipManufacturer = HP; // Hewlett-Packard
|
||||||
else this->ChipManufacturer = UnknownManufacturer; // Unknown manufacturer
|
else this->ChipManufacturer = UnknownManufacturer; // Unknown manufacturer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1809,7 +1813,7 @@ bool SystemInformationImplementation::RetrieveCPUIdentity()
|
||||||
|
|
||||||
; <<CPUID>>
|
; <<CPUID>>
|
||||||
; eax = 1 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision
|
; eax = 1 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision
|
||||||
; ebx: 31..24 - default APIC ID, 23..16 - logical processsor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID
|
; ebx: 31..24 - default APIC ID, 23..16 - logical processor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID
|
||||||
; edx: CPU feature flags
|
; edx: CPU feature flags
|
||||||
mov eax,1
|
mov eax,1
|
||||||
CPUID_INSTRUCTION
|
CPUID_INSTRUCTION
|
||||||
|
@ -1836,8 +1840,6 @@ bool SystemInformationImplementation::RetrieveCPUIdentity()
|
||||||
vbuf[12] = '\0';
|
vbuf[12] = '\0';
|
||||||
this->ChipID.Vendor = vbuf;
|
this->ChipID.Vendor = vbuf;
|
||||||
|
|
||||||
this->FindManufacturer();
|
|
||||||
|
|
||||||
// Retrieve the family of CPU present.
|
// Retrieve the family of CPU present.
|
||||||
this->ChipID.ExtendedFamily = ((localCPUSignature & 0x0FF00000) >> 20); // Bits 27..20 Used
|
this->ChipID.ExtendedFamily = ((localCPUSignature & 0x0FF00000) >> 20); // Bits 27..20 Used
|
||||||
this->ChipID.ExtendedModel = ((localCPUSignature & 0x000F0000) >> 16); // Bits 19..16 Used
|
this->ChipID.ExtendedModel = ((localCPUSignature & 0x000F0000) >> 16); // Bits 19..16 Used
|
||||||
|
@ -2436,7 +2438,7 @@ bool SystemInformationImplementation::RetrieveExtendedCPUFeatures()
|
||||||
#endif
|
#endif
|
||||||
; <<CPUID>>
|
; <<CPUID>>
|
||||||
; eax = 0x80000001 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision
|
; eax = 0x80000001 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision
|
||||||
; ebx: 31..24 - default APIC ID, 23..16 - logical processsor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID
|
; ebx: 31..24 - default APIC ID, 23..16 - logical processor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID
|
||||||
; edx: CPU feature flags
|
; edx: CPU feature flags
|
||||||
mov eax,0x80000001
|
mov eax,0x80000001
|
||||||
CPUID_INSTRUCTION
|
CPUID_INSTRUCTION
|
||||||
|
@ -3002,6 +3004,16 @@ kwsys_stl::string SystemInformationImplementation::ExtractValueFromCpuInfoFile(k
|
||||||
size_t pos2 = buffer.find("\n",pos);
|
size_t pos2 = buffer.find("\n",pos);
|
||||||
if(pos!=buffer.npos && pos2!=buffer.npos)
|
if(pos!=buffer.npos && pos2!=buffer.npos)
|
||||||
{
|
{
|
||||||
|
// It may happen that the beginning matches, but this is still not the requested key.
|
||||||
|
// An example is looking for "cpu" when "cpu family" comes first. So we check that
|
||||||
|
// we have only spaces from here to pos, otherwise we search again.
|
||||||
|
for(size_t i=this->CurrentPositionInFile+strlen(word); i < pos; ++i)
|
||||||
|
{
|
||||||
|
if(buffer[i] != ' ' && buffer[i] != '\t')
|
||||||
|
{
|
||||||
|
return this->ExtractValueFromCpuInfoFile(buffer, word, pos2);
|
||||||
|
}
|
||||||
|
}
|
||||||
return buffer.substr(pos+2,pos2-pos-2);
|
return buffer.substr(pos+2,pos2-pos-2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3073,7 +3085,7 @@ int SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
|
||||||
this->NumberOfLogicalCPU = atoi(cpucount.c_str());
|
this->NumberOfLogicalCPU = atoi(cpucount.c_str());
|
||||||
#endif
|
#endif
|
||||||
// gotta have one, and if this is 0 then we get a / by 0n
|
// gotta have one, and if this is 0 then we get a / by 0n
|
||||||
// beter to have a bad answer than a crash
|
// better to have a bad answer than a crash
|
||||||
if(this->NumberOfPhysicalCPU <= 0)
|
if(this->NumberOfPhysicalCPU <= 0)
|
||||||
{
|
{
|
||||||
this->NumberOfPhysicalCPU = 1;
|
this->NumberOfPhysicalCPU = 1;
|
||||||
|
@ -3082,32 +3094,83 @@ int SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
|
||||||
this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical=
|
this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical=
|
||||||
this->NumberOfLogicalCPU/this->NumberOfPhysicalCPU;
|
this->NumberOfLogicalCPU/this->NumberOfPhysicalCPU;
|
||||||
|
|
||||||
// CPU speed (checking only the first proc
|
// CPU speed (checking only the first processor)
|
||||||
kwsys_stl::string CPUSpeed = this->ExtractValueFromCpuInfoFile(buffer,"cpu MHz");
|
kwsys_stl::string CPUSpeed = this->ExtractValueFromCpuInfoFile(buffer,"cpu MHz");
|
||||||
this->CPUSpeedInMHz = static_cast<float>(atof(CPUSpeed.c_str()));
|
this->CPUSpeedInMHz = static_cast<float>(atof(CPUSpeed.c_str()));
|
||||||
|
|
||||||
// Chip family
|
// Chip family
|
||||||
this->ChipID.Family = atoi(this->ExtractValueFromCpuInfoFile(buffer,"cpu family").c_str());
|
kwsys_stl::string familyStr =
|
||||||
|
this->ExtractValueFromCpuInfoFile(buffer,"cpu family");
|
||||||
|
if(familyStr.empty())
|
||||||
|
{
|
||||||
|
familyStr = this->ExtractValueFromCpuInfoFile(buffer,"CPU architecture");
|
||||||
|
}
|
||||||
|
this->ChipID.Family = atoi(familyStr.c_str());
|
||||||
|
|
||||||
// Chip Vendor
|
// Chip Vendor
|
||||||
this->ChipID.Vendor = this->ExtractValueFromCpuInfoFile(buffer,"vendor_id");
|
this->ChipID.Vendor = this->ExtractValueFromCpuInfoFile(buffer,"vendor_id");
|
||||||
this->FindManufacturer();
|
this->FindManufacturer(familyStr);
|
||||||
|
|
||||||
|
// second try for setting family
|
||||||
|
if (this->ChipID.Family == 0 && this->ChipManufacturer == HP)
|
||||||
|
{
|
||||||
|
if (familyStr == "PA-RISC 1.1a")
|
||||||
|
this->ChipID.Family = 0x11a;
|
||||||
|
else if (familyStr == "PA-RISC 2.0")
|
||||||
|
this->ChipID.Family = 0x200;
|
||||||
|
// If you really get CMake to work on a machine not belonging to
|
||||||
|
// any of those families I owe you a dinner if you get it to
|
||||||
|
// contribute nightly builds regularly.
|
||||||
|
}
|
||||||
|
|
||||||
// Chip Model
|
// Chip Model
|
||||||
this->ChipID.Model = atoi(this->ExtractValueFromCpuInfoFile(buffer,"model").c_str());
|
this->ChipID.Model = atoi(this->ExtractValueFromCpuInfoFile(buffer,"model").c_str());
|
||||||
this->RetrieveClassicalCPUIdentity();
|
if(!this->RetrieveClassicalCPUIdentity())
|
||||||
|
{
|
||||||
|
// Some platforms (e.g. PA-RISC) tell us their CPU name here.
|
||||||
|
// Note: x86 does not.
|
||||||
|
kwsys_stl::string cpuname = this->ExtractValueFromCpuInfoFile(buffer,"cpu");
|
||||||
|
if(!cpuname.empty())
|
||||||
|
{
|
||||||
|
this->ChipID.ProcessorName = cpuname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chip revision
|
||||||
|
kwsys_stl::string cpurev = this->ExtractValueFromCpuInfoFile(buffer,"stepping");
|
||||||
|
if(cpurev.empty())
|
||||||
|
{
|
||||||
|
cpurev = this->ExtractValueFromCpuInfoFile(buffer,"CPU revision");
|
||||||
|
}
|
||||||
|
this->ChipID.Revision = atoi(cpurev.c_str());
|
||||||
|
|
||||||
// Chip Model Name
|
// Chip Model Name
|
||||||
this->ChipID.ModelName = this->ExtractValueFromCpuInfoFile(buffer,"model name").c_str();
|
this->ChipID.ModelName = this->ExtractValueFromCpuInfoFile(buffer,"model name").c_str();
|
||||||
|
|
||||||
// L1 Cache size
|
// L1 Cache size
|
||||||
kwsys_stl::string cacheSize = this->ExtractValueFromCpuInfoFile(buffer,"cache size");
|
// Different architectures may show different names for the caches.
|
||||||
|
// Sum up everything we find.
|
||||||
|
kwsys_stl::vector<const char*> cachename;
|
||||||
|
cachename.clear();
|
||||||
|
|
||||||
|
cachename.push_back("cache size"); // e.g. x86
|
||||||
|
cachename.push_back("I-cache"); // e.g. PA-RISC
|
||||||
|
cachename.push_back("D-cache"); // e.g. PA-RISC
|
||||||
|
|
||||||
|
this->Features.L1CacheSize = 0;
|
||||||
|
for (size_t index = 0; index < cachename.size(); index ++)
|
||||||
|
{
|
||||||
|
kwsys_stl::string cacheSize = this->ExtractValueFromCpuInfoFile(buffer,cachename[index]);
|
||||||
|
if (!cacheSize.empty())
|
||||||
|
{
|
||||||
pos = cacheSize.find(" KB");
|
pos = cacheSize.find(" KB");
|
||||||
if(pos!=cacheSize.npos)
|
if(pos!=cacheSize.npos)
|
||||||
{
|
{
|
||||||
cacheSize = cacheSize.substr(0,pos);
|
cacheSize = cacheSize.substr(0,pos);
|
||||||
}
|
}
|
||||||
this->Features.L1CacheSize = atoi(cacheSize.c_str());
|
this->Features.L1CacheSize += atoi(cacheSize.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2754,9 +2754,15 @@ kwsys_stl::string SystemTools::GetRealPath(const char* path)
|
||||||
|
|
||||||
bool SystemTools::FileIsDirectory(const char* name)
|
bool SystemTools::FileIsDirectory(const char* name)
|
||||||
{
|
{
|
||||||
|
size_t length = strlen(name);
|
||||||
|
if (length == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Remove any trailing slash from the name.
|
// Remove any trailing slash from the name.
|
||||||
char buffer[KWSYS_SYSTEMTOOLS_MAXPATH];
|
char buffer[KWSYS_SYSTEMTOOLS_MAXPATH];
|
||||||
size_t last = strlen(name)-1;
|
size_t last = length-1;
|
||||||
if(last > 0 && (name[last] == '/' || name[last] == '\\')
|
if(last > 0 && (name[last] == '/' || name[last] == '\\')
|
||||||
&& strcmp(name, "/") !=0)
|
&& strcmp(name, "/") !=0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -82,6 +82,14 @@ int test3(int argc, const char* argv[])
|
||||||
|
|
||||||
int test4(int argc, const char* argv[])
|
int test4(int argc, const char* argv[])
|
||||||
{
|
{
|
||||||
|
/* Prepare a pointer to an invalid address. Don't use null, because
|
||||||
|
dereferencing null is undefined behaviour and compilers are free to
|
||||||
|
do whatever they want. ex: Clang will warn at compile time, or even
|
||||||
|
optimize away the write. We hope to 'outsmart' them by using
|
||||||
|
'volatile' and a slightly larger address, based on a runtime value. */
|
||||||
|
volatile int* invalidAddress = 0;
|
||||||
|
invalidAddress += argc?1:2;
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
/* Avoid error diagnostic popups since we are crashing on purpose. */
|
/* Avoid error diagnostic popups since we are crashing on purpose. */
|
||||||
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
|
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
|
||||||
|
@ -94,11 +102,8 @@ int test4(int argc, const char* argv[])
|
||||||
fprintf(stderr, "Output before crash on stderr from crash test.\n");
|
fprintf(stderr, "Output before crash on stderr from crash test.\n");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
#if defined(__clang__)
|
/* Provoke deliberate crash by writing to the invalid address. */
|
||||||
*(int*)1 = 0; /* Clang warns about 0-ptr; undefined behavior. */
|
*invalidAddress = 0;
|
||||||
#else
|
|
||||||
*(int*)0 = 0;
|
|
||||||
#endif
|
|
||||||
fprintf(stdout, "Output after crash on stdout from crash test.\n");
|
fprintf(stdout, "Output after crash on stdout from crash test.\n");
|
||||||
fprintf(stderr, "Output after crash on stderr from crash test.\n");
|
fprintf(stderr, "Output after crash on stderr from crash test.\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1,109 +0,0 @@
|
||||||
/*============================================================================
|
|
||||||
KWSys - Kitware System Library
|
|
||||||
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
|
|
||||||
|
|
||||||
Distributed under the OSI-approved BSD License (the "License");
|
|
||||||
see accompanying file Copyright.txt for details.
|
|
||||||
|
|
||||||
This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
||||||
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
See the License for more information.
|
|
||||||
============================================================================*/
|
|
||||||
#include "kwsysPrivate.h"
|
|
||||||
|
|
||||||
#include KWSYS_HEADER(Registry.hxx)
|
|
||||||
#include KWSYS_HEADER(ios/iostream)
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
// Work-around CMake dependency scanning limitation. This must
|
|
||||||
// duplicate the above list of headers.
|
|
||||||
#if 0
|
|
||||||
# include "Registry.hxx.in"
|
|
||||||
# include "kwsys_ios_iostream.h.in"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define IFT(x,res) if ( !x ) \
|
|
||||||
{ \
|
|
||||||
res = 1; \
|
|
||||||
kwsys_ios::cout << "Error in: " << #x << kwsys_ios::endl; \
|
|
||||||
}
|
|
||||||
#define IFNT(x,res) if ( x ) \
|
|
||||||
{ \
|
|
||||||
res = 1; \
|
|
||||||
kwsys_ios::cout << "Error in: " << #x << kwsys_ios::endl; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CHE(x,y,res) if ( x && strcmp(x,y) ) \
|
|
||||||
{ \
|
|
||||||
res = 1; \
|
|
||||||
kwsys_ios::cout << "Error, " << x << " != " << y << kwsys_ios::endl; \
|
|
||||||
}
|
|
||||||
|
|
||||||
int testRegistry(int, char*[])
|
|
||||||
{
|
|
||||||
int res = 0;
|
|
||||||
|
|
||||||
kwsys::Registry reg;
|
|
||||||
reg.SetTopLevel("TestRegistry");
|
|
||||||
|
|
||||||
IFT(reg.SetValue("TestSubkey", "TestKey1", "Test Value 1"), res);
|
|
||||||
IFT(reg.SetValue("TestSubkey1", "TestKey2", "Test Value 2"), res);
|
|
||||||
IFT(reg.SetValue("TestSubkey", "TestKey3", "Test Value 3"), res);
|
|
||||||
IFT(reg.SetValue("TestSubkey2", "TestKey4", "Test Value 4"), res);
|
|
||||||
|
|
||||||
const char *buffer;
|
|
||||||
IFT(reg.ReadValue("TestSubkey", "TestKey1", &buffer), res);
|
|
||||||
CHE(buffer, "Test Value 1", res);
|
|
||||||
IFT(reg.ReadValue("TestSubkey1", "TestKey2", &buffer), res);
|
|
||||||
CHE(buffer, "Test Value 2", res);
|
|
||||||
IFT(reg.ReadValue("TestSubkey", "TestKey3", &buffer), res);
|
|
||||||
CHE(buffer, "Test Value 3", res);
|
|
||||||
IFT(reg.ReadValue("TestSubkey2", "TestKey4", &buffer), res);
|
|
||||||
CHE(buffer, "Test Value 4", res);
|
|
||||||
|
|
||||||
IFT(reg.SetValue("TestSubkey", "TestKey1", "New Test Value 1"), res);
|
|
||||||
IFT(reg.SetValue("TestSubkey1", "TestKey2", "New Test Value 2"), res);
|
|
||||||
IFT(reg.SetValue("TestSubkey", "TestKey3", "New Test Value 3"), res);
|
|
||||||
IFT(reg.SetValue("TestSubkey2", "TestKey4", "New Test Value 4"), res);
|
|
||||||
|
|
||||||
IFT(reg.ReadValue("TestSubkey", "TestKey1", &buffer), res);
|
|
||||||
CHE(buffer, "New Test Value 1", res);
|
|
||||||
IFT(reg.ReadValue("TestSubkey1", "TestKey2", &buffer), res);
|
|
||||||
CHE(buffer, "New Test Value 2", res);
|
|
||||||
IFT(reg.ReadValue("TestSubkey", "TestKey3", &buffer), res);
|
|
||||||
CHE(buffer, "New Test Value 3", res);
|
|
||||||
IFT(reg.ReadValue("TestSubkey2", "TestKey4", &buffer), res);
|
|
||||||
CHE(buffer, "New Test Value 4", res);
|
|
||||||
|
|
||||||
IFT( reg.DeleteValue("TestSubkey", "TestKey1"), res);
|
|
||||||
IFNT(reg.ReadValue( "TestSubkey", "TestKey1", &buffer), res);
|
|
||||||
IFT( reg.DeleteValue("TestSubkey1", "TestKey2"), res);
|
|
||||||
IFNT(reg.ReadValue( "TestSubkey1", "TestKey2", &buffer), res);
|
|
||||||
IFT( reg.DeleteValue("TestSubkey", "TestKey3"), res);
|
|
||||||
IFNT(reg.ReadValue( "TestSubkey", "TestKey3", &buffer), res);
|
|
||||||
IFT( reg.DeleteValue("TestSubkey2", "TestKey4"), res);
|
|
||||||
IFNT(reg.ReadValue( "TestSubkey2", "TestKey5", &buffer), res);
|
|
||||||
|
|
||||||
const char* longStringWithNewLines = "Value with embedded CR and LF characters CR='\015' LF='\012' CRLF='\015\012'";
|
|
||||||
IFT(reg.SetValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1", longStringWithNewLines), res);
|
|
||||||
IFT(reg.ReadValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1", &buffer), res);
|
|
||||||
CHE(buffer, longStringWithNewLines, res);
|
|
||||||
IFT(reg.DeleteValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1"), res);
|
|
||||||
IFNT(reg.ReadValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1", &buffer), res);
|
|
||||||
|
|
||||||
IFT(reg.SetValue("TestSubkeyWith = EqualSignChar", "TestKey = 1", "Some value"), res);
|
|
||||||
IFT(reg.ReadValue("TestSubkeyWith = EqualSignChar", "TestKey = 1", &buffer), res);
|
|
||||||
CHE(buffer, "Some value", res);
|
|
||||||
IFT(reg.DeleteValue("TestSubkeyWith = EqualSignChar", "TestKey = 1"), res);
|
|
||||||
IFNT(reg.ReadValue("TestSubkeyWith = EqualSignChar", "TestKey = 1", &buffer), res);
|
|
||||||
|
|
||||||
if ( res )
|
|
||||||
{
|
|
||||||
kwsys_ios::cout << "Test failed" << kwsys_ios::endl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
kwsys_ios::cout << "Test passed" << kwsys_ios::endl;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
|
@ -66,6 +66,7 @@ int testSystemInformation(int, char*[])
|
||||||
printMethod(info, GetFamilyID);
|
printMethod(info, GetFamilyID);
|
||||||
printMethod(info, GetModelID);
|
printMethod(info, GetModelID);
|
||||||
printMethod(info, GetExtendedProcessorName);
|
printMethod(info, GetExtendedProcessorName);
|
||||||
|
printMethod(info, GetSteppingCode);
|
||||||
printMethod(info, GetProcessorSerialNumber);
|
printMethod(info, GetProcessorSerialNumber);
|
||||||
printMethod2(info, GetProcessorCacheSize, "KB");
|
printMethod2(info, GetProcessorCacheSize, "KB");
|
||||||
printMethod(info, GetLogicalProcessorsPerPhysical);
|
printMethod(info, GetLogicalProcessorsPerPhysical);
|
||||||
|
|
Loading…
Reference in New Issue