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_Process 1)
|
||||
SET(KWSYS_USE_RegularExpression 1)
|
||||
SET(KWSYS_USE_Registry 1)
|
||||
SET(KWSYS_USE_System 1)
|
||||
SET(KWSYS_USE_SystemTools 1)
|
||||
SET(KWSYS_USE_CommandLineArguments 1)
|
||||
|
@ -762,7 +761,7 @@ SET(KWSYS_HXX_FILES Configure String
|
|||
# Add selected C++ classes.
|
||||
SET(cppclasses
|
||||
Directory DynamicLoader Glob RegularExpression SystemTools
|
||||
CommandLineArguments Registry IOStream SystemInformation
|
||||
CommandLineArguments IOStream SystemInformation
|
||||
)
|
||||
FOREACH(cpp ${cppclasses})
|
||||
IF(KWSYS_USE_${cpp})
|
||||
|
@ -800,12 +799,8 @@ SET(KWSYS_CXX_SRCS)
|
|||
# Add the proper sources for this platform's Process implementation.
|
||||
IF(KWSYS_USE_Process)
|
||||
IF(NOT UNIX)
|
||||
# Use the Windows implementation. We need the encoded forwarding executable.
|
||||
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)
|
||||
# Use the Windows implementation.
|
||||
SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessWin32.c)
|
||||
ELSE(NOT UNIX)
|
||||
# Use the UNIX implementation.
|
||||
SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessUNIX.c)
|
||||
|
@ -937,43 +932,6 @@ IF(KWSYS_USE_String)
|
|||
COMPILE_FLAGS "-DKWSYS_STRING_C")
|
||||
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.
|
||||
IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
|
||||
|
@ -1012,7 +970,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
|
|||
)
|
||||
ENDIF(NOT WATCOM)
|
||||
SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
|
||||
testRegistry
|
||||
testIOS
|
||||
testSystemTools
|
||||
testCommandLineArguments
|
||||
|
@ -1116,8 +1073,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
|
|||
# We expect test to fail
|
||||
SET_TESTS_PROPERTIES(kwsys.testFail PROPERTIES WILL_FAIL ON)
|
||||
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")
|
||||
MESSAGE(STATUS "GET_TEST_PROPERTY returned: ${wfv}")
|
||||
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
|
||||
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
|
||||
|
@ -91,18 +83,12 @@ Q190351 and Q150956.
|
|||
# define KWSYSPE_DEBUG(x) (void)1
|
||||
#endif
|
||||
|
||||
#define kwsysEncodedWriteArrayProcessFwd9x kwsys_ns(EncodedWriteArrayProcessFwd9x)
|
||||
|
||||
typedef LARGE_INTEGER kwsysProcessTime;
|
||||
|
||||
typedef struct kwsysProcessCreateInformation_s
|
||||
{
|
||||
/* Windows child startup control data. */
|
||||
STARTUPINFO StartupInfo;
|
||||
|
||||
/* Special error reporting pipe for Win9x forwarding executable. */
|
||||
HANDLE ErrorPipeRead;
|
||||
HANDLE ErrorPipeWrite;
|
||||
} kwsysProcessCreateInformation;
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
@ -146,7 +132,6 @@ static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProc
|
|||
static void kwsysProcessSetExitException(kwsysProcess* cp, int code);
|
||||
static void kwsysProcessKillTree(int pid);
|
||||
static void kwsysProcessDisablePipeThreads(kwsysProcess* cp);
|
||||
extern kwsysEXPORT int kwsysEncodedWriteArrayProcessFwd9x(const char* fname);
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* A structure containing synchronization data for each thread. */
|
||||
|
@ -233,15 +218,6 @@ struct kwsysProcess_s
|
|||
/* Whether to treat command lines as 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. */
|
||||
HANDLE SharedIndexMutex;
|
||||
|
||||
|
@ -269,9 +245,6 @@ struct kwsysProcess_s
|
|||
HANDLE PipeNativeSTDOUT[2];
|
||||
HANDLE PipeNativeSTDERR[2];
|
||||
|
||||
/* Handle to automatically delete the Win9x forwarding executable. */
|
||||
HANDLE Win9xHandle;
|
||||
|
||||
/* ------------- Data managed per call to Execute ------------- */
|
||||
|
||||
/* The exceptional behavior that terminated the process, if any. */
|
||||
|
@ -311,7 +284,7 @@ struct kwsysProcess_s
|
|||
for pipes to close after process termination. */
|
||||
int PipesLeft;
|
||||
|
||||
/* Buffer for error messages (possibly from Win9x child). */
|
||||
/* Buffer for error messages. */
|
||||
char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1];
|
||||
|
||||
/* Description for the ExitException. */
|
||||
|
@ -337,9 +310,6 @@ kwsysProcess* kwsysProcess_New(void)
|
|||
/* Process control structure. */
|
||||
kwsysProcess* cp;
|
||||
|
||||
/* Path to Win9x forwarding executable. */
|
||||
char* win9x = 0;
|
||||
|
||||
/* Windows version number data. */
|
||||
OSVERSIONINFO osv;
|
||||
|
||||
|
@ -365,73 +335,11 @@ kwsysProcess* kwsysProcess_New(void)
|
|||
GetVersionEx(&osv);
|
||||
if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
|
||||
{
|
||||
/* This is Win9x. We need the console forwarding executable to
|
||||
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);
|
||||
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;
|
||||
}
|
||||
/* Win9x no longer supported. */
|
||||
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. */
|
||||
if(!(cp->SharedIndexMutex = CreateSemaphore(0, 1, 1, 0)))
|
||||
{
|
||||
|
@ -446,30 +354,6 @@ kwsysProcess* kwsysProcess_New(void)
|
|||
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. */
|
||||
for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
|
||||
{
|
||||
|
@ -620,13 +504,6 @@ void kwsysProcess_Delete(kwsysProcess* cp)
|
|||
kwsysProcessCleanupHandle(&cp->SharedIndexMutex);
|
||||
kwsysProcessCleanupHandle(&cp->Full);
|
||||
|
||||
/* Close the Win9x resume and kill event handles. */
|
||||
if(cp->Win9x)
|
||||
{
|
||||
kwsysProcessCleanupHandle(&cp->Win9xResumeEvent);
|
||||
kwsysProcessCleanupHandle(&cp->Win9xKillEvent);
|
||||
}
|
||||
|
||||
/* Free memory. */
|
||||
kwsysProcess_SetCommand(cp, 0);
|
||||
kwsysProcess_SetWorkingDirectory(cp, 0);
|
||||
|
@ -637,12 +514,6 @@ void kwsysProcess_Delete(kwsysProcess* cp)
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1017,21 +888,6 @@ void kwsysProcess_Execute(kwsysProcess* cp)
|
|||
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. */
|
||||
ZeroMemory(&si, sizeof(si));
|
||||
si.StartupInfo.cb = sizeof(si.StartupInfo);
|
||||
|
@ -1130,8 +986,6 @@ void kwsysProcess_Execute(kwsysProcess* cp)
|
|||
STD_OUTPUT_HANDLE);
|
||||
kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError,
|
||||
STD_ERROR_HANDLE);
|
||||
kwsysProcessCleanupHandle(&si.ErrorPipeRead);
|
||||
kwsysProcessCleanupHandle(&si.ErrorPipeWrite);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1160,16 +1014,9 @@ void kwsysProcess_Execute(kwsysProcess* cp)
|
|||
|
||||
/* All processes in the pipeline have been started in suspended
|
||||
mode. Resume them all now. */
|
||||
if(cp->Win9x)
|
||||
for(i=0; i < cp->NumberOfCommands; ++i)
|
||||
{
|
||||
SetEvent(cp->Win9xResumeEvent);
|
||||
}
|
||||
else
|
||||
{
|
||||
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. ----- */
|
||||
|
@ -1480,21 +1327,12 @@ void kwsysProcess_Kill(kwsysProcess* cp)
|
|||
|
||||
/* Kill the children. */
|
||||
cp->Killed = 1;
|
||||
if(cp->Win9x)
|
||||
for(i=0; i < cp->NumberOfCommands; ++i)
|
||||
{
|
||||
/* 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)
|
||||
{
|
||||
kwsysProcessKillTree(cp->ProcessInformation[i].dwProcessId);
|
||||
// close the handle if we kill it
|
||||
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread);
|
||||
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess);
|
||||
}
|
||||
kwsysProcessKillTree(cp->ProcessInformation[i].dwProcessId);
|
||||
// close the handle if we kill it
|
||||
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread);
|
||||
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess);
|
||||
}
|
||||
|
||||
/* We are killing the children and ignoring all data. Do not wait
|
||||
|
@ -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
|
||||
children have been created before running any one. */
|
||||
r = CreateProcess(0, realCommand, 0, 0, TRUE,
|
||||
cp->Win9x? 0 : CREATE_SUSPENDED, 0, 0,
|
||||
&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)
|
||||
if(!CreateProcess(0, cp->Commands[index], 0, 0, TRUE, CREATE_SUSPENDED, 0,
|
||||
0, &si->StartupInfo, &cp->ProcessInformation[index]))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Successfully created this child process. Close the current
|
||||
process's copies of the inherited stdout and stdin handles. The
|
||||
|
@ -2152,19 +1906,12 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error)
|
|||
/* Cleanup any processes already started in a suspended state. */
|
||||
if(cp->ProcessInformation)
|
||||
{
|
||||
if(cp->Win9x)
|
||||
for(i=0; i < cp->NumberOfCommands; ++i)
|
||||
{
|
||||
SetEvent(cp->Win9xKillEvent);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i=0; i < cp->NumberOfCommands; ++i)
|
||||
if(cp->ProcessInformation[i].hProcess)
|
||||
{
|
||||
if(cp->ProcessInformation[i].hProcess)
|
||||
{
|
||||
TerminateProcess(cp->ProcessInformation[i].hProcess, 255);
|
||||
WaitForSingleObject(cp->ProcessInformation[i].hProcess, INFINITE);
|
||||
}
|
||||
TerminateProcess(cp->ProcessInformation[i].hProcess, 255);
|
||||
WaitForSingleObject(cp->ProcessInformation[i].hProcess, INFINITE);
|
||||
}
|
||||
}
|
||||
for(i=0; i < cp->NumberOfCommands; ++i)
|
||||
|
|
|
@ -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
|
||||
{
|
||||
AMD, Intel, NSC, UMC, Cyrix, NexGen, IDT, Rise, Transmeta, Sun, IBM,
|
||||
Motorola, UnknownManufacturer
|
||||
Motorola, HP, UnknownManufacturer
|
||||
};
|
||||
|
||||
protected:
|
||||
|
@ -346,7 +346,7 @@ protected:
|
|||
static void Delay (unsigned int);
|
||||
static void DelayOverhead (unsigned int);
|
||||
|
||||
void FindManufacturer();
|
||||
void FindManufacturer(const kwsys_stl::string &family = "");
|
||||
|
||||
// For Mac
|
||||
bool ParseSysCtl();
|
||||
|
@ -1144,6 +1144,7 @@ void SystemInformationImplementation::RunCPUCheck()
|
|||
{
|
||||
// Retrieve the CPU details.
|
||||
RetrieveCPUIdentity();
|
||||
this->FindManufacturer();
|
||||
RetrieveCPUFeatures();
|
||||
}
|
||||
|
||||
|
@ -1415,6 +1416,8 @@ const char * SystemInformationImplementation::GetVendorID()
|
|||
return "IBM";
|
||||
case Motorola:
|
||||
return "Motorola";
|
||||
case HP:
|
||||
return "Hewlett-Packard";
|
||||
default:
|
||||
return "Unknown Manufacturer";
|
||||
}
|
||||
|
@ -1670,7 +1673,7 @@ bool SystemInformationImplementation::RetrieveCPUFeatures()
|
|||
#endif
|
||||
; <<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
|
||||
; 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
|
||||
mov eax,1
|
||||
CPUID_INSTRUCTION
|
||||
|
@ -1755,7 +1758,7 @@ bool SystemInformationImplementation::RetrieveCPUFeatures()
|
|||
|
||||
|
||||
/** 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.
|
||||
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 == "IBM") this->ChipManufacturer = IBM; // IBM 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
|
||||
}
|
||||
|
||||
|
@ -1809,7 +1813,7 @@ bool SystemInformationImplementation::RetrieveCPUIdentity()
|
|||
|
||||
; <<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
|
||||
; 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
|
||||
mov eax,1
|
||||
CPUID_INSTRUCTION
|
||||
|
@ -1836,8 +1840,6 @@ bool SystemInformationImplementation::RetrieveCPUIdentity()
|
|||
vbuf[12] = '\0';
|
||||
this->ChipID.Vendor = vbuf;
|
||||
|
||||
this->FindManufacturer();
|
||||
|
||||
// Retrieve the family of CPU present.
|
||||
this->ChipID.ExtendedFamily = ((localCPUSignature & 0x0FF00000) >> 20); // Bits 27..20 Used
|
||||
this->ChipID.ExtendedModel = ((localCPUSignature & 0x000F0000) >> 16); // Bits 19..16 Used
|
||||
|
@ -2436,7 +2438,7 @@ bool SystemInformationImplementation::RetrieveExtendedCPUFeatures()
|
|||
#endif
|
||||
; <<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
|
||||
; 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
|
||||
mov eax,0x80000001
|
||||
CPUID_INSTRUCTION
|
||||
|
@ -3002,6 +3004,16 @@ kwsys_stl::string SystemInformationImplementation::ExtractValueFromCpuInfoFile(k
|
|||
size_t pos2 = buffer.find("\n",pos);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -3073,7 +3085,7 @@ int SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
|
|||
this->NumberOfLogicalCPU = atoi(cpucount.c_str());
|
||||
#endif
|
||||
// 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)
|
||||
{
|
||||
this->NumberOfPhysicalCPU = 1;
|
||||
|
@ -3082,32 +3094,83 @@ int SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
|
|||
this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical=
|
||||
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");
|
||||
this->CPUSpeedInMHz = static_cast<float>(atof(CPUSpeed.c_str()));
|
||||
|
||||
// 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
|
||||
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
|
||||
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
|
||||
this->ChipID.ModelName = this->ExtractValueFromCpuInfoFile(buffer,"model name").c_str();
|
||||
|
||||
// L1 Cache size
|
||||
kwsys_stl::string cacheSize = this->ExtractValueFromCpuInfoFile(buffer,"cache size");
|
||||
pos = cacheSize.find(" KB");
|
||||
if(pos!=cacheSize.npos)
|
||||
// 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 ++)
|
||||
{
|
||||
cacheSize = cacheSize.substr(0,pos);
|
||||
kwsys_stl::string cacheSize = this->ExtractValueFromCpuInfoFile(buffer,cachename[index]);
|
||||
if (!cacheSize.empty())
|
||||
{
|
||||
pos = cacheSize.find(" KB");
|
||||
if(pos!=cacheSize.npos)
|
||||
{
|
||||
cacheSize = cacheSize.substr(0,pos);
|
||||
}
|
||||
this->Features.L1CacheSize += atoi(cacheSize.c_str());
|
||||
}
|
||||
}
|
||||
this->Features.L1CacheSize = atoi(cacheSize.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -2754,9 +2754,15 @@ kwsys_stl::string SystemTools::GetRealPath(const char* path)
|
|||
|
||||
bool SystemTools::FileIsDirectory(const char* name)
|
||||
{
|
||||
size_t length = strlen(name);
|
||||
if (length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove any trailing slash from the name.
|
||||
char buffer[KWSYS_SYSTEMTOOLS_MAXPATH];
|
||||
size_t last = strlen(name)-1;
|
||||
size_t last = length-1;
|
||||
if(last > 0 && (name[last] == '/' || name[last] == '\\')
|
||||
&& strcmp(name, "/") !=0)
|
||||
{
|
||||
|
|
|
@ -82,6 +82,14 @@ int test3(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)
|
||||
/* Avoid error diagnostic popups since we are crashing on purpose. */
|
||||
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");
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
#if defined(__clang__)
|
||||
*(int*)1 = 0; /* Clang warns about 0-ptr; undefined behavior. */
|
||||
#else
|
||||
*(int*)0 = 0;
|
||||
#endif
|
||||
/* Provoke deliberate crash by writing to the invalid address. */
|
||||
*invalidAddress = 0;
|
||||
fprintf(stdout, "Output after crash on stdout from crash test.\n");
|
||||
fprintf(stderr, "Output after crash on stderr from crash test.\n");
|
||||
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, GetModelID);
|
||||
printMethod(info, GetExtendedProcessorName);
|
||||
printMethod(info, GetSteppingCode);
|
||||
printMethod(info, GetProcessorSerialNumber);
|
||||
printMethod2(info, GetProcessorCacheSize, "KB");
|
||||
printMethod(info, GetLogicalProcessorsPerPhysical);
|
||||
|
|
Loading…
Reference in New Issue