diff --git a/CHANGES b/CHANGES
index 4b3b4089..b6155eb1 100644
--- a/CHANGES
+++ b/CHANGES
@@ -686,3 +686,6 @@ unreleased Version 0.3.40
* really updated dparser to a6207d6db5e54c68aa4b9db53b702681242d81d5
* goto definition on import now supports package.d
* bugzilla 13759: $(VSINSTALLDIR)\Common7\IDE now added to the default executable paths
+ * build phobos browse info: operated on outdated folder structure of phobos/druntime
+ * DMD/x64 linker override settings not saved
+ * revamped pipedmd: now uses tracker.exe from MSBuild or WinSDK to monitor dependencies
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 8cf50f58..8a126f0a 100644
--- a/Makefile
+++ b/Makefile
@@ -163,8 +163,7 @@ install: all cpp2d_exe idl2d_exe
cd nsis && "$(NSIS)\makensis" /V1 visuald.nsi
"$(ZIP)" -j ..\downloads\visuald_pdb.zip bin\release\visuald.pdb bin\release\vdserver.pdb
-#prerequisites
-install_vs: visuald_vs vdserver cv2pdb dparser vdextension mago install_only
+install_vs: prerequisites visuald_vs vdserver cv2pdb dparser vdextension mago install_only
install_only:
cd nsis && "$(NSIS)\makensis" /V1 visuald.nsi
diff --git a/TODO b/TODO
index 8e347fbf..6fdd51b0 100644
--- a/TODO
+++ b/TODO
@@ -33,7 +33,7 @@ Project:
- GDC:
- separate compile + link does not write to object dir
- ddoc files
-- additional options for resource compiler
++ additional options for resource compiler
- pass import path from static lib project to dependent projects
- single file compilation for file configuration
- custom command: quotes in dependencies not supported
@@ -167,3 +167,6 @@ Unsorted
- jump to assertion error
+ import std.container: jump to package
- renaming configuration does not change project config
+- win32coff support
+- file search: replace . with \ in path search?
+- run cv2pdb disabled for GDC/x64
diff --git a/build/build.visualdproj b/build/build.visualdproj
index 55c05b06..5365e2ee 100644
--- a/build/build.visualdproj
+++ b/build/build.visualdproj
@@ -49,6 +49,8 @@
0
0
0
+ $(CC) -c
+ 1
$(DMDInstallDir)windows\bin\dmd.exe
@@ -147,6 +149,8 @@
0
0
0
+ $(CC) -c
+ 1
$(DMDInstallDir)windows\bin\dmd.exe
@@ -201,7 +205,7 @@ echo. >$(TargetDir)\build.dep
-
+
+
diff --git a/tools/pipedmd.d b/tools/pipedmd.d
index 00cd8a75..9eeb5ca8 100644
--- a/tools/pipedmd.d
+++ b/tools/pipedmd.d
@@ -8,7 +8,7 @@
module pipedmd;
import std.stdio;
-import std.c.windows.windows;
+import core.sys.windows.windows;
import std.windows.charset;
import core.stdc.string;
import std.string;
@@ -18,415 +18,554 @@ import std.array;
import std.algorithm;
import std.conv;
import std.path;
+import std.process;
import std.utf;
-extern(C)
+alias core.stdc.stdio.stdout stdout;
+
+static bool isIdentifierChar(char ch)
{
- struct PROCESS_INFORMATION {
- HANDLE hProcess;
- HANDLE hThread;
- DWORD dwProcessId;
- DWORD dwThreadId;
- }
-
- alias PROCESS_INFORMATION* LPPROCESS_INFORMATION;
-
- struct STARTUPINFOA {
- DWORD cb;
- LPSTR lpReserved;
- LPSTR lpDesktop;
- LPSTR lpTitle;
- DWORD dwX;
- DWORD dwY;
- DWORD dwXSize;
- DWORD dwYSize;
- DWORD dwXCountChars;
- DWORD dwYCountChars;
- DWORD dwFillAttribute;
- DWORD dwFlags;
- WORD wShowWindow;
- WORD cbReserved2;
- LPBYTE lpReserved2;
- HANDLE hStdInput;
- HANDLE hStdOutput;
- HANDLE hStdError;
- }
-
- alias STARTUPINFOA* LPSTARTUPINFOA;
-
- enum
- {
- CP_ACP = 0,
- CP_OEMCP = 1,
- CP_MACCP = 2,
- CP_THREAD_ACP = 3,
- CP_SYMBOL = 42,
- CP_UTF7 = 65000,
- CP_UTF8 = 65001
- }
+ // include C++,Pascal,Windows mangling and UTF8 encoding and compression
+ return ch >= 0x80 || (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_';
}
-extern(System)
+static bool isDigit(char ch)
{
- BOOL CreatePipe(
- HANDLE* hReadPipe,
- HANDLE* hWritePipe,
- SECURITY_ATTRIBUTES* lpPipeAttributes,
- DWORD nSize
- );
-
- BOOL SetHandleInformation(
- HANDLE hObject,
- DWORD dwMask,
- DWORD dwFlags
- );
-
- BOOL
- CreateProcessA(
- LPCSTR lpApplicationName,
- LPSTR lpCommandLine,
- LPSECURITY_ATTRIBUTES lpProcessAttributes,
- LPSECURITY_ATTRIBUTES lpThreadAttributes,
- BOOL bInheritHandles,
- DWORD dwCreationFlags,
- LPVOID lpEnvironment,
- LPCSTR lpCurrentDirectory,
- LPSTARTUPINFOA lpStartupInfo,
- LPPROCESS_INFORMATION lpProcessInformation
- );
-
- BOOL
- GetExitCodeProcess(
- HANDLE hProcess,
- LPDWORD lpExitCode
- );
-
- BOOL
- PeekNamedPipe(
- HANDLE hNamedPipe,
- LPVOID lpBuffer,
- DWORD nBufferSize,
- LPDWORD lpBytesRead,
- LPDWORD lpTotalBytesAvail,
- LPDWORD lpBytesLeftThisMessage
- );
-
- UINT GetKBCodePage();
+ return (ch >= '0' && ch <= '9');
}
-enum uint HANDLE_FLAG_INHERIT = 0x00000001;
-enum uint HANDLE_FLAG_PROTECT_FROM_CLOSE = 0x00000002;
+string quoteArg(string arg)
+{
+ if(countUntil(arg, ' ') < arg.length)
+ return "\"" ~ replace(arg, "\"", "\\\"") ~ "\"";
+ else
+ return arg;
+}
-enum uint STARTF_USESHOWWINDOW = 0x00000001;
-enum uint STARTF_USESIZE = 0x00000002;
-enum uint STARTF_USEPOSITION = 0x00000004;
-enum uint STARTF_USECOUNTCHARS = 0x00000008;
-enum uint STARTF_USEFILLATTRIBUTE = 0x00000010;
-enum uint STARTF_RUNFULLSCREEN = 0x00000020; // ignored for non-x86 platforms
-enum uint STARTF_FORCEONFEEDBACK = 0x00000040;
-enum uint STARTF_FORCEOFFFEEDBACK = 0x00000080;
-enum uint STARTF_USESTDHANDLES = 0x00000100;
+int main(string[] argv)
+{
+ if(argv.length < 2)
+ {
+ printf("pipedmd V0.2, written 2012 by Benjamin Thaut, complications improved by Rainer Schuetze\n");
+ printf("decompresses and demangles names in OPTLINK and ld messages\n");
+ printf("\n");
+ printf("usage: %.*s [-nodemangle] [-gdcmode | -msmode] [-deps depfile] [executable] [arguments]\n",
+ argv[0].length, argv[0].ptr);
+ return -1;
+ }
+ int skipargs = 0;
+ string depsfile;
+ bool doDemangle = true;
+ bool gdcMode = false; //gcc linker
+ bool msMode = false; //microsft linker
+ bool verbose = false;
+
+ while (argv.length >= skipargs + 2)
+ {
+ if(argv[skipargs + 1] == "-nodemangle")
+ {
+ doDemangle = false;
+ skipargs = 1;
+ }
+ else if(argv[skipargs + 1] == "-gdcmode")
+ {
+ gdcMode = true;
+ skipargs++;
+ }
+ else if(argv[skipargs + 1] == "-msmode")
+ {
+ msMode = true;
+ skipargs++;
+ }
+ else if(argv[skipargs + 1] == "-verbose")
+ {
+ verbose = true;
+ skipargs++;
+ }
+ else if(argv[skipargs + 1] == "-deps")
+ depsfile = argv[skipargs += 2];
+ else
+ break;
+ }
+
+ string exe = (argv.length > skipargs + 1 ? argv[skipargs + 1] : null);
+ string command;
+ string trackdir;
+ string trackfile;
+
+ bool inject = false;
+ if (depsfile.length > 0)
+ {
+ string fullexe = findExeInPath(exe);
+ bool isX64 = isExe64bit(fullexe);
+ if (verbose)
+ if (fullexe.empty)
+ printf ("%.*s not found in PATH, assuming %d-bit application\n", exe.length, exe.ptr, isX64 ? 64 : 32);
+ else
+ printf ("%.*s is a %d-bit application\n", fullexe.length, fullexe.ptr, isX64 ? 64 : 32);
+
+ string tracker = findTracker(isX64);
+ if (tracker.length > 0)
+ {
+ command = quoteArg(tracker);
+ trackdir = dirName(depsfile);
+ if (trackdir != ".")
+ command ~= " /if " ~ quoteArg(trackdir);
+ trackfile = stripExtension(baseName(exe)) ~ ".read.*.tlog";
+ string trackfilewr = stripExtension(baseName(exe)) ~ ".write.*.tlog";
+ foreach(f; std.file.dirEntries(trackdir, std.file.SpanMode.shallow))
+ if (globMatch(baseName(f), trackfile) || globMatch(baseName(f), trackfilewr))
+ std.file.remove(f);
+ command ~= " /c";
+ }
+ else if (isX64)
+ {
+ printf("cannot monitor 64-bit executable %.*s, no suitable tracker.exe found\n", exe.length, exe.ptr);
+ return -1;
+ }
+ else
+ inject = true;
+ }
+
+ for(int i = skipargs + 1;i < argv.length; i++)
+ {
+ if(command.length > 0)
+ command ~= " ";
+ command ~= quoteArg(argv[i]);
+ }
+ if(verbose)
+ printf("Command: %.*s\n", command.length, command.ptr);
+
+ int exitCode = runProcess(command, inject ? depsfile : null, doDemangle, gdcMode, msMode);
+
+ if (exitCode == 0 && trackfile.length > 0)
+ {
+ ubyte[] buf;
+ foreach(f; std.file.dirEntries(trackdir, std.file.SpanMode.shallow))
+ if (globMatch(baseName(f), trackfile))
+ {
+ ubyte[] fbuf = cast(ubyte[])std.file.read(f);
+ // strip BOM from all but the first file
+ if (buf.length && fbuf.length > 1 && fbuf[0] == 0xFF && fbuf[1] == 0xFE)
+ fbuf = fbuf[2..$];
+ buf ~= fbuf;
+ }
+
+ std.file.write(depsfile, buf);
+ }
+
+ return exitCode;
+}
-enum uint CREATE_SUSPENDED = 0x00000004;
+int runProcess(string command, string depsfile, bool doDemangle, bool gdcMode, bool msMode)
+{
+ HANDLE hStdOutRead;
+ HANDLE hStdOutWrite;
+ HANDLE hStdInRead;
+ HANDLE hStdInWrite;
+
+ SECURITY_ATTRIBUTES saAttr;
+
+ // Set the bInheritHandle flag so pipe handles are inherited.
+
+ saAttr.nLength = SECURITY_ATTRIBUTES.sizeof;
+ saAttr.bInheritHandle = TRUE;
+ saAttr.lpSecurityDescriptor = null;
+
+ // Create a pipe for the child process's STDOUT.
+
+ if ( ! CreatePipe(&hStdOutRead, &hStdOutWrite, &saAttr, 0) )
+ assert(0);
+
+ // Ensure the read handle to the pipe for STDOUT is not inherited.
+
+ if ( ! SetHandleInformation(hStdOutRead, HANDLE_FLAG_INHERIT, 0) )
+ assert(0);
+
+ if ( ! CreatePipe(&hStdInRead, &hStdInWrite, &saAttr, 0) )
+ assert(0);
+
+ if ( ! SetHandleInformation(hStdInWrite, HANDLE_FLAG_INHERIT, 0) )
+ assert(0);
+
+ PROCESS_INFORMATION piProcInfo;
+ STARTUPINFOA siStartInfo;
+ BOOL bSuccess = FALSE;
+
+ // Set up members of the PROCESS_INFORMATION structure.
+
+ memset( &piProcInfo, 0, PROCESS_INFORMATION.sizeof );
+
+ // Set up members of the STARTUPINFO structure.
+ // This structure specifies the STDIN and STDOUT handles for redirection.
+
+ memset( &siStartInfo, 0, STARTUPINFOA.sizeof );
+ siStartInfo.cb = STARTUPINFOA.sizeof;
+ siStartInfo.hStdError = hStdOutWrite;
+ siStartInfo.hStdOutput = hStdOutWrite;
+ siStartInfo.hStdInput = hStdInRead;
+ siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
+
+ int cp = GetKBCodePage();
+ auto szCommand = toMBSz(command, cp);
+ bSuccess = CreateProcessA(null,
+ cast(char*)szCommand, // command line
+ null, // process security attributes
+ null, // primary thread security attributes
+ TRUE, // handles are inherited
+ CREATE_SUSPENDED, // creation flags
+ null, // use parent's environment
+ null, // use parent's current directory
+ &siStartInfo, // STARTUPINFO pointer
+ &piProcInfo); // receives PROCESS_INFORMATION
+
+ if(!bSuccess)
+ {
+ printf("failed launching %s\n", szCommand);
+ return 1;
+ }
+
+ if(depsfile)
+ InjectDLL(piProcInfo.hProcess, depsfile);
+ ResumeThread(piProcInfo.hThread);
+
+ char[] buffer = new char[2048];
+ WCHAR[] decodeBufferWide;
+ char[] decodeBuffer;
+ DWORD bytesRead = 0;
+ DWORD bytesAvaiable = 0;
+ DWORD exitCode = 0;
+ bool linkerFound = gdcMode || msMode;
+
+ while(true)
+ {
+ bSuccess = PeekNamedPipe(hStdOutRead, buffer.ptr, buffer.length, &bytesRead, &bytesAvaiable, null);
+ if(bSuccess && bytesAvaiable > 0)
+ {
+ size_t lineLength = 0;
+ for(; lineLength < buffer.length && lineLength < bytesAvaiable && buffer[lineLength] != '\n'; lineLength++){}
+ if(lineLength >= bytesAvaiable)
+ {
+ // if no line end found, retry with larger buffer
+ if(lineLength >= buffer.length)
+ buffer.length = buffer.length * 2;
+ continue;
+ }
+ bSuccess = ReadFile(hStdOutRead, buffer.ptr, lineLength+1, &bytesRead, null);
+ if(!bSuccess || bytesRead == 0)
+ break;
+
+ bytesRead--; //remove \n
+ while(bytesRead > 0 && buffer[bytesRead-1] == '\r') // remove \r
+ bytesRead--;
+ DWORD skip = 0;
+ while(skip < bytesRead && buffer[skip] == '\r') // remove \r
+ skip++;
+
+ char[] output = buffer[skip..bytesRead];
+ if(msMode) //the microsoft linker outputs the error messages in the default ANSI codepage so we need to convert it to UTF-8
+ {
+ if(decodeBufferWide.length < output.length + 1)
+ {
+ decodeBufferWide.length = output.length + 1;
+ decodeBuffer.length = 2 * output.length + 1;
+ }
+ auto numDecoded = MultiByteToWideChar(CP_ACP, 0, output.ptr, output.length, decodeBufferWide.ptr, decodeBufferWide.length);
+ auto numEncoded = WideCharToMultiByte(CP_UTF8, 0, decodeBufferWide.ptr, numDecoded, decodeBuffer.ptr, decodeBuffer.length, null, null);
+ output = decodeBuffer[0..numEncoded];
+ }
+ size_t writepos = 0;
+
+ if(!linkerFound)
+ {
+ if (output.startsWith("OPTLINK (R)"))
+ linkerFound = true;
+ else if(output.countUntil("error LNK") >= 0 || output.countUntil("warning LNK") >= 0)
+ linkerFound = msMode = true;
+ }
+
+ if(doDemangle && linkerFound)
+ {
+ if(gdcMode)
+ {
+ if(output.countUntil("undefined reference to") >= 0 || output.countUntil("In function") >= 0)
+ {
+ processLine(output, writepos, false, cp);
+ }
+ }
+ else if(msMode)
+ {
+ if(output.countUntil("LNK") >= 0)
+ {
+ processLine(output, writepos, false, cp);
+ }
+ }
+ else
+ {
+ processLine(output, writepos, true, cp);
+ }
+ }
+ if(writepos < output.length)
+ fwrite(output.ptr + writepos, output.length - writepos, 1, stdout);
+ fputc('\n', stdout);
+ }
+ else
+ {
+ bSuccess = GetExitCodeProcess(piProcInfo.hProcess, &exitCode);
+ if(!bSuccess || exitCode != 259) //259 == STILL_ACTIVE
+ break;
+ Sleep(5);
+ }
+ }
+
+ //close the handles to the process
+ CloseHandle(hStdInWrite);
+ CloseHandle(hStdOutRead);
+ CloseHandle(piProcInfo.hProcess);
+ CloseHandle(piProcInfo.hThread);
+
+ return exitCode;
+}
-alias std.c.stdio.stdout stdout;
+void processLine(char[] output, ref size_t writepos, bool optlink, int cp)
+{
+ for(int p = 0; p < output.length; p++)
+ {
+ if(isIdentifierChar(output[p]))
+ {
+ int q = p;
+ while(p < output.length && isIdentifierChar(output[p]))
+ p++;
+
+ auto symbolName = output[q..p];
+ const(char)[] realSymbolName = symbolName;
+ if(optlink)
+ {
+ size_t pos = 0;
+ realSymbolName = decodeDmdString(symbolName, pos);
+ if(pos != p - q)
+ {
+ // could not decode, might contain UTF8 elements, so try translating to the current code page
+ // (demangling will not work anyway)
+ try
+ {
+ auto szName = toMBSz(symbolName, cp);
+ auto plen = strlen(szName);
+ realSymbolName = szName[0..plen];
+ pos = p - q;
+ }
+ catch(Exception)
+ {
+ realSymbolName = null;
+ }
+ }
+ }
+ if(realSymbolName.length)
+ {
+ if(realSymbolName != symbolName)
+ {
+ // not sure if output is UTF8 encoded, so avoid any translation
+ if(q > writepos)
+ fwrite(output.ptr + writepos, q - writepos, 1, stdout);
+ fwrite(realSymbolName.ptr, realSymbolName.length, 1, stdout);
+ writepos = p;
+ }
+ while(realSymbolName.length > 1 && realSymbolName[0] == '_')
+ realSymbolName = realSymbolName[1..$];
+ if(realSymbolName.length > 2 && realSymbolName[0] == 'D' && isDigit(realSymbolName[1]))
+ {
+ try
+ {
+ symbolName = demangle(realSymbolName);
+ }
+ catch(Exception)
+ {
+ }
+ if(realSymbolName != symbolName)
+ {
+ // skip a trailing quote
+ if(p + 1 < output.length && (output[p+1] == '\'' || output[p+1] == '\"'))
+ p++;
+ if(p > writepos)
+ fwrite(output.ptr + writepos, p - writepos, 1, stdout);
+ writepos = p;
+ fwrite(" (".ptr, 2, 1, stdout);
+ fwrite(symbolName.ptr, symbolName.length, 1, stdout);
+ fwrite(")".ptr, 1, 1, stdout);
+ }
+ }
+ }
+ }
+ }
+}
-static bool isIdentifierChar(char ch)
+///////////////////////////////////////////////////////////////////////////////
+bool isExe64bit(string exe)
+//out(res) { printf("isExe64bit: %.*s %d-bit\n", exe.length, exe.ptr, res ? 64 : 32); }
+body
{
- // include C++,Pascal,Windows mangling and UTF8 encoding and compression
- return ch >= 0x80 || (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_';
+ if (exe is null || !std.file.exists(exe))
+ return false;
+
+ try
+ {
+ File f = File(exe, "rb");
+ IMAGE_DOS_HEADER dosHdr;
+ f.rawRead((&dosHdr)[0..1]);
+ if (dosHdr.e_magic != IMAGE_DOS_SIGNATURE)
+ return false;
+ f.seek(dosHdr.e_lfanew);
+ IMAGE_NT_HEADERS ntHdr;
+ f.rawRead((&ntHdr)[0..1]);
+ return ntHdr.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64
+ || ntHdr.FileHeader.Machine == IMAGE_FILE_MACHINE_IA64;
+ }
+ catch(Exception)
+ {
+ }
+ return false;
}
-static bool isDigit(char ch)
+string findExeInPath(string exe)
{
- return (ch >= '0' && ch <= '9');
+ if (std.path.baseName(exe) != exe)
+ return exe; // if the file has dir component, don't search path
+
+ string path = std.process.environment["PATH"];
+ string[] paths = split(path, ";");
+ string ext = extension(exe);
+
+ foreach(p; paths)
+ {
+ if (p.length > 0 && p[0] == '"' && p[$-1] == '"') // remove quotes
+ p = p[1 .. $-1];
+ p = std.path.buildPath(p, exe);
+ if(std.file.exists(p))
+ return p;
+
+ if (ext.empty)
+ {
+ if(std.file.exists(p ~ ".exe"))
+ return p ~ ".exe";
+ if(std.file.exists(p ~ ".com"))
+ return p ~ ".com";
+ if(std.file.exists(p ~ ".bat"))
+ return p ~ ".bat";
+ if(std.file.exists(p ~ ".cmd"))
+ return p ~ ".cmd";
+ }
+ }
+ return null;
}
-int main(string[] argv)
+enum SECURE_ACCESS = ~(WRITE_DAC | WRITE_OWNER | GENERIC_ALL | ACCESS_SYSTEM_SECURITY);
+enum KEY_WOW64_32KEY = 0x200;
+enum KEY_WOW64_64KEY = 0x100;
+
+string findTracker(bool x64)
+{
+ string exe = findExeInPath("tracker.exe");
+ if (!exe.empty && isExe64bit(exe) != x64)
+ exe = null;
+
+ if (exe.empty)
+ exe = findTrackerInMSBuild (r"SOFTWARE\Microsoft\MSBuild\ToolsVersions\12.0"w.ptr, x64);
+ if (exe.empty)
+ exe = findTrackerInMSBuild (r"SOFTWARE\Microsoft\MSBuild\ToolsVersions\11.0"w.ptr, x64);
+ if (exe.empty)
+ exe = findTrackerInMSBuild (r"SOFTWARE\Microsoft\MSBuild\ToolsVersions\10.0"w.ptr, x64);
+ if (exe.empty)
+ exe = findTrackerInSDK(x64);
+ return exe;
+}
+
+string trackerPath(string binpath, bool x64)
{
- if(argv.length < 2)
- {
- printf("pipedmd V0.2, written 2012 by Benjamin Thaut, complications improved by Rainer Schuetze\n");
- printf("decompresses and demangles names in OPTLINK and ld messages\n");
- printf("\n");
- printf("usage: %.*s [-nodemangle] [-gdcmode | -msmode] [-deps depfile] [executable] [arguments]\n",
- argv[0].length, argv[0].ptr);
- return -1;
- }
- int skipargs;
- string depsfile;
- bool doDemangle = true;
- bool gdcMode = false; //gcc linker
- bool msMode = false; //microsft linker
-
- if(argv.length >= 2 && argv[1] == "-nodemangle")
- {
- doDemangle = false;
- skipargs = 1;
- }
- if(argv.length >= skipargs + 2 && argv[skipargs + 1] == "-gdcmode")
- {
- gdcMode = true;
- skipargs++;
- }
- if(argv.length >= skipargs + 2 && argv[skipargs + 1] == "-msmode")
- {
- msMode = true;
- skipargs++;
- }
- if(argv.length > skipargs + 2 && argv[skipargs + 1] == "-deps")
- depsfile = argv[skipargs += 2];
-
- string command; //= "gdc";
- for(int i = skipargs + 1;i < argv.length; i++)
- {
- if(command.length > 0)
- command ~= " ";
- if(countUntil(argv[i], ' ') < argv[i].length)
- command ~= "\"" ~ replace(argv[i], "\"", "\\\"") ~ "\"";
- else
- command ~= argv[i];
- }
-
- HANDLE hStdOutRead;
- HANDLE hStdOutWrite;
- HANDLE hStdInRead;
- HANDLE hStdInWrite;
-
- SECURITY_ATTRIBUTES saAttr;
-
- // Set the bInheritHandle flag so pipe handles are inherited.
-
- saAttr.nLength = SECURITY_ATTRIBUTES.sizeof;
- saAttr.bInheritHandle = TRUE;
- saAttr.lpSecurityDescriptor = null;
-
- // Create a pipe for the child process's STDOUT.
-
- if ( ! CreatePipe(&hStdOutRead, &hStdOutWrite, &saAttr, 0) )
- assert(0);
-
- // Ensure the read handle to the pipe for STDOUT is not inherited.
-
- if ( ! SetHandleInformation(hStdOutRead, HANDLE_FLAG_INHERIT, 0) )
- assert(0);
-
- if ( ! CreatePipe(&hStdInRead, &hStdInWrite, &saAttr, 0) )
- assert(0);
-
- if ( ! SetHandleInformation(hStdInWrite, HANDLE_FLAG_INHERIT, 0) )
- assert(0);
-
- PROCESS_INFORMATION piProcInfo;
- STARTUPINFOA siStartInfo;
- BOOL bSuccess = FALSE;
-
- // Set up members of the PROCESS_INFORMATION structure.
-
- memset( &piProcInfo, 0, PROCESS_INFORMATION.sizeof );
-
- // Set up members of the STARTUPINFO structure.
- // This structure specifies the STDIN and STDOUT handles for redirection.
-
- memset( &siStartInfo, 0, STARTUPINFOA.sizeof );
- siStartInfo.cb = STARTUPINFOA.sizeof;
- siStartInfo.hStdError = hStdOutWrite;
- siStartInfo.hStdOutput = hStdOutWrite;
- siStartInfo.hStdInput = hStdInRead;
- siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
-
- int cp = GetKBCodePage();
- auto szCommand = toMBSz(command, cp);
- bSuccess = CreateProcessA(null,
- cast(char*)szCommand, // command line
- null, // process security attributes
- null, // primary thread security attributes
- TRUE, // handles are inherited
- CREATE_SUSPENDED, // creation flags
- null, // use parent's environment
- null, // use parent's current directory
- &siStartInfo, // STARTUPINFO pointer
- &piProcInfo); // receives PROCESS_INFORMATION
-
- if(!bSuccess)
- {
- printf("failed launching %s\n", szCommand);
- return 1;
- }
-
- if(depsfile.length)
- InjectDLL(piProcInfo.hProcess, depsfile);
- ResumeThread(piProcInfo.hThread);
-
- char[] buffer = new char[2048];
- WCHAR[] decodeBufferWide;
- char[] decodeBuffer;
- DWORD bytesRead = 0;
- DWORD bytesAvaiable = 0;
- DWORD exitCode = 0;
- bool linkerFound = gdcMode || msMode;
-
- while(true)
- {
- bSuccess = PeekNamedPipe(hStdOutRead, buffer.ptr, buffer.length, &bytesRead, &bytesAvaiable, null);
- if(bSuccess && bytesAvaiable > 0)
- {
- size_t lineLength = 0;
- for(; lineLength < buffer.length && lineLength < bytesAvaiable && buffer[lineLength] != '\n'; lineLength++){}
- if(lineLength >= bytesAvaiable)
- {
- // if no line end found, retry with larger buffer
- if(lineLength >= buffer.length)
- buffer.length = buffer.length * 2;
- continue;
- }
- bSuccess = ReadFile(hStdOutRead, buffer.ptr, lineLength+1, &bytesRead, null);
- if(!bSuccess || bytesRead == 0)
- break;
-
- bytesRead--; //remove \n
- while(bytesRead > 0 && buffer[bytesRead-1] == '\r') // remove \r
- bytesRead--;
- DWORD skip = 0;
- while(skip < bytesRead && buffer[skip] == '\r') // remove \r
- skip++;
-
- char[] output = buffer[skip..bytesRead];
- if(msMode) //the microsoft linker outputs the error messages in the default ANSI codepage so we need to convert it to UTF-8
- {
- if(decodeBufferWide.length < output.length + 1)
- {
- decodeBufferWide.length = output.length + 1;
- decodeBuffer.length = 2 * output.length + 1;
- }
- auto numDecoded = MultiByteToWideChar(CP_ACP, 0, output.ptr, output.length, decodeBufferWide.ptr, decodeBufferWide.length);
- auto numEncoded = WideCharToMultiByte(CP_UTF8, 0, decodeBufferWide.ptr, numDecoded, decodeBuffer.ptr, decodeBuffer.length, null, null);
- output = decodeBuffer[0..numEncoded];
- }
- size_t writepos = 0;
-
- if(!linkerFound)
- {
- if (output.startsWith("OPTLINK (R)"))
- linkerFound = true;
- else if(output.countUntil("error LNK") >= 0 || output.countUntil("warning LNK") >= 0)
- linkerFound = msMode = true;
- }
-
- if(doDemangle && linkerFound)
- {
- void processLine(bool optlink)
- {
- for(int p = 0; p < output.length; p++)
- {
- if(isIdentifierChar(output[p]))
- {
- int q = p;
- while(p < output.length && isIdentifierChar(output[p]))
- p++;
-
- auto symbolName = output[q..p];
- const(char)[] realSymbolName = symbolName;
- if(optlink)
- {
- size_t pos = 0;
- realSymbolName = decodeDmdString(symbolName, pos);
- if(pos != p - q)
- {
- // could not decode, might contain UTF8 elements, so try translating to the current code page
- // (demangling will not work anyway)
- try
- {
- auto szName = toMBSz(symbolName, cp);
- auto plen = strlen(szName);
- realSymbolName = szName[0..plen];
- pos = p - q;
- }
- catch(Exception)
- {
- realSymbolName = null;
- }
- }
- }
- if(realSymbolName.length)
- {
- if(realSymbolName != symbolName)
- {
- // not sure if output is UTF8 encoded, so avoid any translation
- if(q > writepos)
- fwrite(output.ptr + writepos, q - writepos, 1, stdout);
- fwrite(realSymbolName.ptr, realSymbolName.length, 1, stdout);
- writepos = p;
- }
- while(realSymbolName.length > 1 && realSymbolName[0] == '_')
- realSymbolName = realSymbolName[1..$];
- if(realSymbolName.length > 2 && realSymbolName[0] == 'D' && isDigit(realSymbolName[1]))
- {
- try
- {
- symbolName = demangle(realSymbolName);
- }
- catch(Exception)
- {
- }
- if(realSymbolName != symbolName)
- {
- // skip a trailing quote
- if(p + 1 < output.length && (output[p+1] == '\'' || output[p+1] == '\"'))
- p++;
- if(p > writepos)
- fwrite(output.ptr + writepos, p - writepos, 1, stdout);
- writepos = p;
- fwrite(" (".ptr, 2, 1, stdout);
- fwrite(symbolName.ptr, symbolName.length, 1, stdout);
- fwrite(")".ptr, 1, 1, stdout);
- }
- }
- }
- }
- }
- }
-
- if(gdcMode)
- {
- if(output.countUntil("undefined reference to") >= 0 || output.countUntil("In function") >= 0)
- {
- processLine(false);
- }
- }
- else if(msMode)
- {
- if(output.countUntil("LNK") >= 0)
- {
- processLine(false);
- }
- }
- else
- {
- processLine(true);
- }
- }
- if(writepos < output.length)
- fwrite(output.ptr + writepos, output.length - writepos, 1, stdout);
- fputc('\n', stdout);
- }
- else
- {
- bSuccess = GetExitCodeProcess(piProcInfo.hProcess, &exitCode);
- if(!bSuccess || exitCode != 259) //259 == STILL_ACTIVE
- break;
- Sleep(5);
- }
- }
-
-
- //close the handles to the process
- CloseHandle(hStdInWrite);
- CloseHandle(hStdOutRead);
- CloseHandle(piProcInfo.hProcess);
- CloseHandle(piProcInfo.hThread);
-
- return exitCode;
+ if (binpath.empty)
+ return null;
+ string exe = buildPath(binpath, "tracker.exe");
+ //printf("trying %.*s\n", exe.length, exe.ptr);
+ if (!std.file.exists(exe))
+ return null;
+ if (isExe64bit(exe) != x64)
+ return null;
+ return exe;
+}
+
+string findTrackerInMSBuild (const(wchar)* keyname, bool x64)
+{
+ string path = readRegistry(keyname, "MSBuildToolsPath"w.ptr, x64);
+ return trackerPath(path, x64);
+}
+
+string findTrackerInSDK (bool x64)
+{
+ wstring suffix = x64 ? "-x64" : "-x86";
+ wstring sdk = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows";
+ HKEY key;
+ LONG lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE, sdk.ptr, 0,
+ KEY_READ | KEY_WOW64_32KEY, &key); // always in Wow6432
+ if (lRes != ERROR_SUCCESS)
+ return null;
+
+ string exe;
+ DWORD idx = 0;
+ wchar[100] ver;
+ DWORD len = ver.length;
+ while (RegEnumKeyExW(key, idx, ver.ptr, &len, null, null, null, null) == ERROR_SUCCESS)
+ {
+ const(wchar)[] sdkver = sdk ~ r"\"w ~ ver[0..len];
+ const(wchar)* wsdkver = toUTF16z(sdkver);
+ HKEY verkey;
+ lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE, wsdkver, 0, KEY_READ | KEY_WOW64_32KEY, &verkey); // always in Wow6432
+ if (lRes == ERROR_SUCCESS)
+ {
+ DWORD veridx = 0;
+ wchar[100] sub;
+ len = sub.length;
+ while (RegEnumKeyExW(verkey, veridx, sub.ptr, &len, null, null, null, null) == ERROR_SUCCESS)
+ {
+ const(wchar)[] sdkversub = sdkver ~ r"\"w ~ sub[0..len];
+ string path = readRegistry(toUTF16z(sdkversub), "InstallationFolder"w.ptr, false);
+ exe = trackerPath(path, x64);
+ if (!exe.empty)
+ break;
+ veridx++;
+ }
+ RegCloseKey(verkey);
+ }
+ idx++;
+ if (!exe.empty)
+ break;
+ }
+ RegCloseKey(key);
+
+ return exe;
+}
+
+string readRegistry(const(wchar)* keyname, const(wchar)* valname, bool x64)
+{
+ string path;
+ HKEY key;
+ LONG lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyname, 0,
+ KEY_READ | (x64 ? KEY_WOW64_64KEY : KEY_WOW64_32KEY), &key);
+ //printf("RegOpenKeyExW = %d, key=%x\n", lRes, key);
+ if (lRes == ERROR_SUCCESS)
+ {
+ DWORD type;
+ DWORD cntBytes;
+ int hr = RegQueryValueExW(key, valname, null, &type, null, &cntBytes);
+ //printf("RegQueryValueW = %d, %d words\n", hr, cntBytes);
+ if (hr == ERROR_SUCCESS || hr == ERROR_MORE_DATA)
+ {
+ wchar[] wpath = new wchar[(cntBytes + 1) / 2];
+ hr = RegQueryValueExW(key, valname, null, &type, wpath.ptr, &cntBytes);
+ if (hr == ERROR_SUCCESS)
+ path = toUTF8(wpath[0..$-1]); // strip trailing 0
+ }
+ RegCloseKey(key);
+ }
+ return path;
}
///////////////////////////////////////////////////////////////////////////////
@@ -437,69 +576,214 @@ extern(Windows) BOOL
WriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T * lpNumberOfBytesWritten);
extern(Windows) HANDLE
CreateRemoteThread(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize,
- LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId);
+ LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId);
void InjectDLL(HANDLE hProcess, string depsfile)
{
- HANDLE hThread, hRemoteModule;
-
- HMODULE appmod = GetModuleHandleA(null);
- wchar[] wmodname = new wchar[260];
- DWORD len = GetModuleFileNameW(appmod, wmodname.ptr, wmodname.length);
- if(len > wmodname.length)
- {
- wmodname = new wchar[len + 1];
- GetModuleFileNameW(null, wmodname.ptr, len + 1);
- }
- string modpath = to!string(wmodname);
- string dll = buildPath(std.path.dirName(modpath), "filemonitor.dll");
-
- auto wdll = to!wstring(dll) ~ cast(wchar)0;
- // detect offset of dumpFile
- HMODULE fmod = LoadLibraryW(wdll.ptr);
- if(!fmod)
- return;
- size_t addr = cast(size_t)GetProcAddress(fmod, "_D11filemonitor8dumpFileG260a");
- FreeLibrary(fmod);
- if(addr == 0)
- return;
- addr = addr - cast(size_t)fmod;
-
- // copy path to other process
+ HANDLE hThread, hRemoteModule;
+
+ HMODULE appmod = GetModuleHandleA(null);
+ wchar[] wmodname = new wchar[260];
+ DWORD len = GetModuleFileNameW(appmod, wmodname.ptr, wmodname.length);
+ if(len > wmodname.length)
+ {
+ wmodname = new wchar[len + 1];
+ GetModuleFileNameW(null, wmodname.ptr, len + 1);
+ }
+ string modpath = to!string(wmodname);
+ string dll = buildPath(std.path.dirName(modpath), "filemonitor.dll");
+
+ auto wdll = to!wstring(dll) ~ cast(wchar)0;
+ // detect offset of dumpFile
+ HMODULE fmod = LoadLibraryW(wdll.ptr);
+ if(!fmod)
+ return;
+ size_t addr = cast(size_t)GetProcAddress(fmod, "_D11filemonitor8dumpFileG260a");
+ FreeLibrary(fmod);
+ if(addr == 0)
+ return;
+ addr = addr - cast(size_t)fmod;
+
+ // copy path to other process
auto wdllRemote = VirtualAllocEx(hProcess, null, wdll.length * 2, MEM_COMMIT, PAGE_READWRITE);
- auto procWrite = getWriteProcFunc();
- procWrite(hProcess, wdllRemote, wdll.ptr, wdll.length * 2, null);
+ auto procWrite = getWriteProcFunc();
+ procWrite(hProcess, wdllRemote, wdll.ptr, wdll.length * 2, null);
- // load dll into other process, assuming LoadLibraryW is at the same address in all processes
- HMODULE mod = GetModuleHandleA("Kernel32");
- auto proc = GetProcAddress(mod, "LoadLibraryW");
- hThread = getCreateRemoteThreadFunc()(hProcess, null, 0, cast(LPTHREAD_START_ROUTINE)proc, wdllRemote, 0, null);
- WaitForSingleObject(hThread, INFINITE);
+ // load dll into other process, assuming LoadLibraryW is at the same address in all processes
+ HMODULE mod = GetModuleHandleA("Kernel32");
+ auto proc = GetProcAddress(mod, "LoadLibraryW");
+ hThread = getCreateRemoteThreadFunc()(hProcess, null, 0, cast(LPTHREAD_START_ROUTINE)proc, wdllRemote, 0, null);
+ WaitForSingleObject(hThread, INFINITE);
- // Get handle of the loaded module
- GetExitCodeThread(hThread, cast(DWORD*) &hRemoteModule);
+ // Get handle of the loaded module
+ GetExitCodeThread(hThread, cast(DWORD*) &hRemoteModule);
- // Clean up
- CloseHandle(hThread);
- VirtualFreeEx(hProcess, wdllRemote, wdll.length * 2, MEM_RELEASE);
+ // Clean up
+ CloseHandle(hThread);
+ VirtualFreeEx(hProcess, wdllRemote, wdll.length * 2, MEM_RELEASE);
- void* pDumpFile = cast(char*)hRemoteModule + addr;
- // printf("remotemod = %p, addr = %p\n", hRemoteModule, pDumpFile);
- auto szDepsFile = toMBSz(depsfile);
+ void* pDumpFile = cast(char*)hRemoteModule + addr;
+ // printf("remotemod = %p, addr = %p\n", hRemoteModule, pDumpFile);
+ auto szDepsFile = toMBSz(depsfile);
- procWrite(hProcess, pDumpFile, szDepsFile, strlen(szDepsFile) + 1, null);
+ procWrite(hProcess, pDumpFile, szDepsFile, strlen(szDepsFile) + 1, null);
}
typeof(WriteProcessMemory)* getWriteProcFunc ()
{
- HMODULE mod = GetModuleHandleA("Kernel32");
- auto proc = GetProcAddress(mod, "WriteProcessMemory");
- return cast(typeof(WriteProcessMemory)*)proc;
+ HMODULE mod = GetModuleHandleA("Kernel32");
+ auto proc = GetProcAddress(mod, "WriteProcessMemory");
+ return cast(typeof(WriteProcessMemory)*)proc;
}
typeof(CreateRemoteThread)* getCreateRemoteThreadFunc ()
{
- HMODULE mod = GetModuleHandleA("Kernel32");
- auto proc = GetProcAddress(mod, "CreateRemoteThread");
- return cast(typeof(CreateRemoteThread)*)proc;
-}
\ No newline at end of file
+ HMODULE mod = GetModuleHandleA("Kernel32");
+ auto proc = GetProcAddress(mod, "CreateRemoteThread");
+ return cast(typeof(CreateRemoteThread)*)proc;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+extern(C)
+{
+ struct PROCESS_INFORMATION
+ {
+ HANDLE hProcess;
+ HANDLE hThread;
+ DWORD dwProcessId;
+ DWORD dwThreadId;
+ }
+
+ alias PROCESS_INFORMATION* LPPROCESS_INFORMATION;
+
+ struct STARTUPINFOA
+ {
+ DWORD cb;
+ LPSTR lpReserved;
+ LPSTR lpDesktop;
+ LPSTR lpTitle;
+ DWORD dwX;
+ DWORD dwY;
+ DWORD dwXSize;
+ DWORD dwYSize;
+ DWORD dwXCountChars;
+ DWORD dwYCountChars;
+ DWORD dwFillAttribute;
+ DWORD dwFlags;
+ WORD wShowWindow;
+ WORD cbReserved2;
+ LPBYTE lpReserved2;
+ HANDLE hStdInput;
+ HANDLE hStdOutput;
+ HANDLE hStdError;
+ }
+
+ alias STARTUPINFOA* LPSTARTUPINFOA;
+
+ enum
+ {
+ CP_ACP = 0,
+ CP_OEMCP = 1,
+ CP_MACCP = 2,
+ CP_THREAD_ACP = 3,
+ CP_SYMBOL = 42,
+ CP_UTF7 = 65000,
+ CP_UTF8 = 65001
+ }
+
+ enum IMAGE_DOS_SIGNATURE = 0x5A4D; // MZ
+
+ struct IMAGE_DOS_HEADER // DOS .EXE header
+ {
+ WORD e_magic; // Magic number
+ WORD e_cblp; // Bytes on last page of file
+ WORD e_cp; // Pages in file
+ WORD e_crlc; // Relocations
+ WORD e_cparhdr; // Size of header in paragraphs
+ WORD e_minalloc; // Minimum extra paragraphs needed
+ WORD e_maxalloc; // Maximum extra paragraphs needed
+ WORD e_ss; // Initial (relative) SS value
+ WORD e_sp; // Initial SP value
+ WORD e_csum; // Checksum
+ WORD e_ip; // Initial IP value
+ WORD e_cs; // Initial (relative) CS value
+ WORD e_lfarlc; // File address of relocation table
+ WORD e_ovno; // Overlay number
+ WORD e_res[4]; // Reserved words
+ WORD e_oemid; // OEM identifier (for e_oeminfo)
+ WORD e_oeminfo; // OEM information; e_oemid specific
+ WORD e_res2[10]; // Reserved words
+ LONG e_lfanew; // File address of new exe header
+ }
+
+ struct IMAGE_NT_HEADERS
+ {
+ DWORD Signature;
+ IMAGE_FILE_HEADER FileHeader;
+ // IMAGE_OPTIONAL_HEADER32 OptionalHeader;
+ }
+
+ enum IMAGE_FILE_MACHINE_IA64 = 0x0200; // Intel 64
+ enum IMAGE_FILE_MACHINE_AMD64 = 0x8664; // AMD64 (K8)
+
+ struct IMAGE_FILE_HEADER
+ {
+ WORD Machine;
+ WORD NumberOfSections;
+ DWORD TimeDateStamp;
+ DWORD PointerToSymbolTable;
+ DWORD NumberOfSymbols;
+ WORD SizeOfOptionalHeader;
+ WORD Characteristics;
+ }
+}
+
+extern(System)
+{
+ BOOL CreatePipe(HANDLE* hReadPipe,
+ HANDLE* hWritePipe,
+ SECURITY_ATTRIBUTES* lpPipeAttributes,
+ DWORD nSize);
+
+ BOOL SetHandleInformation(HANDLE hObject,
+ DWORD dwMask,
+ DWORD dwFlags);
+
+ BOOL CreateProcessA(LPCSTR lpApplicationName,
+ LPSTR lpCommandLine,
+ LPSECURITY_ATTRIBUTES lpProcessAttributes,
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ BOOL bInheritHandles,
+ DWORD dwCreationFlags,
+ LPVOID lpEnvironment,
+ LPCSTR lpCurrentDirectory,
+ LPSTARTUPINFOA lpStartupInfo,
+ LPPROCESS_INFORMATION lpProcessInformation);
+
+ BOOL GetExitCodeProcess(HANDLE hProcess,
+ LPDWORD lpExitCode);
+
+ BOOL PeekNamedPipe(HANDLE hNamedPipe,
+ LPVOID lpBuffer,
+ DWORD nBufferSize,
+ LPDWORD lpBytesRead,
+ LPDWORD lpTotalBytesAvail,
+ LPDWORD lpBytesLeftThisMessage);
+
+ UINT GetKBCodePage();
+}
+
+enum uint HANDLE_FLAG_INHERIT = 0x00000001;
+enum uint HANDLE_FLAG_PROTECT_FROM_CLOSE = 0x00000002;
+
+enum uint STARTF_USESHOWWINDOW = 0x00000001;
+enum uint STARTF_USESIZE = 0x00000002;
+enum uint STARTF_USEPOSITION = 0x00000004;
+enum uint STARTF_USECOUNTCHARS = 0x00000008;
+enum uint STARTF_USEFILLATTRIBUTE = 0x00000010;
+enum uint STARTF_RUNFULLSCREEN = 0x00000020; // ignored for non-x86 platforms
+enum uint STARTF_FORCEONFEEDBACK = 0x00000040;
+enum uint STARTF_FORCEOFFFEEDBACK = 0x00000080;
+enum uint STARTF_USESTDHANDLES = 0x00000100;
+
+enum uint CREATE_SUSPENDED = 0x00000004;
diff --git a/vdc/parser.visualdproj b/vdc/parser.visualdproj
index f33b6cbc..1f23d7e7 100644
--- a/vdc/parser.visualdproj
+++ b/vdc/parser.visualdproj
@@ -12,6 +12,7 @@
0
0
0
+ 0
1
0
0
@@ -48,6 +49,8 @@
0
0
0
+ $(CC) -c
+ 1
m:\s\d\rainers\windows\bin\dmd_msc.exe
..
.
@@ -109,6 +112,7 @@
0
0
0
+ 0
0
1
0
@@ -119,7 +123,7 @@
0
0
0
- 0
+ 1
0
0
0
@@ -145,6 +149,8 @@
0
0
0
+ $(CC) -c
+ 1
m:\s\d\rainers\windows\bin\dmd_msc.exe
..
.
@@ -206,6 +212,7 @@
0
0
0
+ 0
0
1
0
@@ -242,6 +249,8 @@
0
0
0
+ $(CC) -c
+ 1
m:\s\d\rainers\windows\bin\dmd.exe
..
.
@@ -303,6 +312,7 @@
0
0
0
+ 0
1
0
0
@@ -339,6 +349,8 @@
0
0
0
+ $(CC) -c
+ 1
m:\s\d\rainers\windows\bin\dmd_msc.exe
..
.
@@ -400,6 +412,7 @@
0
0
0
+ 0
0
1
0
@@ -436,6 +449,8 @@
0
0
1
+ $(CC) -c
+ 1
m:\s\d\rainers\windows\bin\dmd_msc.exe
..
.
@@ -497,6 +512,7 @@
0
0
0
+ 0
1
0
0
@@ -533,6 +549,8 @@
0
0
0
+ $(CC) -c
+ 1
m:\s\d\rainers\windows\bin\dmd.exe
..
.
@@ -594,6 +612,7 @@
0
0
0
+ 0
0
0
0
@@ -630,6 +649,8 @@
0
1
0
+ $(CC) -c
+ 1
m:\s\d\rainers\windows\bin\dmd_msc.exe
..
.
@@ -691,6 +712,7 @@
0
0
0
+ 0
0
0
0
@@ -727,6 +749,8 @@
0
1
0
+ $(CC) -c
+ 1
m:\s\d\rainers\windows\bin\dmd_msc.exe
..
.
@@ -788,6 +812,7 @@
0
0
0
+ 0
0
0
0
@@ -824,6 +849,8 @@
0
2
0
+ $(CC) -c
+ 1
m:\s\d\rainers\windows\bin\dmd_msc.exe
..
.
@@ -885,6 +912,7 @@
0
0
0
+ 0
0
0
0
@@ -921,6 +949,8 @@
0
2
0
+ $(CC) -c
+ 1
m:\s\d\rainers\windows\bin\dmd_msc.exe
..
.
@@ -982,6 +1012,7 @@
0
0
0
+ 0
1
0
0
@@ -1018,6 +1049,8 @@
0
0
0
+ $(CC) -c
+ 1
m:\s\d\rainers\windows\bin\dmd_msc.exe
..
.
@@ -1079,6 +1112,7 @@
0
0
0
+ 0
1
0
0
@@ -1115,6 +1149,8 @@
0
0
1
+ $(CC) -c
+ 1
m:\s\d\rainers\windows\bin\dmd_msc.exe
..
.
diff --git a/visuald/build.d b/visuald/build.d
index dc29d1e0..0e84f0ef 100644
--- a/visuald/build.d
+++ b/visuald/build.d
@@ -465,8 +465,11 @@ else
lnkdeps = fromMBSz(lnkdepz.ptr, cp);
}
string[] lnkfiles = splitLines(lnkdeps);
- makeFilenamesAbsolute(lnkfiles, workdir);
- files ~= lnkfiles;
+ foreach(lnkfile; lnkfiles)
+ {
+ if(!lnkfile.startsWith("#Command:"))
+ files ~= makeFilenameAbsolute(lnkfile, workdir);
+ }
}
return true;
}
diff --git a/visuald/dpackage.d b/visuald/dpackage.d
index 4373a2ae..6973a720 100644
--- a/visuald/dpackage.d
+++ b/visuald/dpackage.d
@@ -18,11 +18,13 @@ import std.file;
import std.conv;
import std.array;
import std.exception;
+import std.algorithm;
import stdext.path;
import stdext.array;
import stdext.file;
import stdext.string;
+import stdext.registry;
import visuald.comutil;
import visuald.hierutil;
@@ -1409,6 +1411,9 @@ class GlobalOptions
keyToolOpts.Set("ExeSearchPath64", toUTF16(DMD.ExeSearchPath64));
keyToolOpts.Set("LibSearchPath64", toUTF16(DMD.LibSearchPath64));
+ keyToolOpts.Set("overrideIni64", DMD.overrideIni64);
+ keyToolOpts.Set("overrideLinker64", toUTF16(DMD.overrideLinker64));
+ keyToolOpts.Set("overrideOptions64", toUTF16(DMD.overrideOptions64));
keyToolOpts.Set("GDC.ExeSearchPath64", toUTF16(GDC.ExeSearchPath64));
keyToolOpts.Set("GDC.LibSearchPath64", toUTF16(GDC.LibSearchPath64));
keyToolOpts.Set("LDC.ExeSearchPath64", toUTF16(LDC.ExeSearchPath64));
@@ -1728,7 +1733,7 @@ class GlobalOptions
return null;
}
- string[] findDFiles(string path, string sub)
+ string[] findDFiles(string path, string sub, bool deep)
{
string[] files;
if(!isExistingDir(path ~ sub))
@@ -1737,6 +1742,13 @@ class GlobalOptions
{
if(_startsWith(file, path))
file = file[path.length .. $];
+ if (deep && isExistingDir(path ~ file))
+ {
+ string[] exclude = [ "\\internal", "\\freebsd", "\\linux", "\\osx", "\\posix", "\\solaris" ];
+ if (!any!(e => file.endsWith(e))(exclude))
+ files ~= findDFiles(path, file, deep);
+ continue;
+ }
string bname = baseName(file);
if(globMatch(bname, "openrj.d"))
continue;
@@ -1817,31 +1829,24 @@ class GlobalOptions
if(std.file.exists(s ~ "std\\algorithm.d")) // D2
{
- files ~= findDFiles(s, "std");
- files ~= findDFiles(s, "std\\c");
- files ~= findDFiles(s, "std\\c\\windows");
- files ~= findDFiles(s, "std\\internal\\math");
- files ~= findDFiles(s, "std\\windows");
- files ~= findDFiles(s, "etc\\c");
+ files ~= findDFiles(s, "std", true);
+ files ~= findDFiles(s, "etc\\c", true);
jsonfile = jsonPath ~ "phobos.json";
}
if(std.file.exists(s ~ "std\\gc.d")) // D1
{
- files ~= findDFiles(s, "std");
- files ~= findDFiles(s, "std\\c");
- files ~= findDFiles(s, "std\\c\\windows");
- files ~= findDFiles(s, "std\\windows");
+ files ~= findDFiles(s, "std", false);
+ files ~= findDFiles(s, "std\\c", false);
+ files ~= findDFiles(s, "std\\c\\windows", false);
+ files ~= findDFiles(s, "std\\windows", false);
jsonfile = jsonPath ~ "phobos1.json";
}
if(std.file.exists(s ~ "object.di"))
{
opts ~= " -I" ~ buildPath(s, "..\\src"); // needed since dmd 2.059
files ~= "object.di";
- files ~= findDFiles(s, "core");
- files ~= findDFiles(s, "core\\stdc");
- files ~= findDFiles(s, "core\\sync");
- files ~= findDFiles(s, "core\\sys\\windows");
- files ~= findDFiles(s, "std");
+ files ~= findDFiles(s, "core", true);
+ files ~= findDFiles(s, "std", false); // D1?
jsonfile = jsonPath ~ "druntime.json";
}
diff --git a/visuald/register.d b/visuald/register.d
index 0b31e562..ee7d2705 100644
--- a/visuald/register.d
+++ b/visuald/register.d
@@ -20,6 +20,7 @@ import std.datetime;
import std.array;
import stdext.string;
+import stdext.registry;
import visuald.dpackage;
import visuald.dllmain;
@@ -27,8 +28,6 @@ import visuald.propertypage;
import visuald.config;
import visuald.comutil;
-enum { SECURE_ACCESS = ~(WRITE_DAC | WRITE_OWNER | GENERIC_ALL | ACCESS_SYSTEM_SECURITY) }
-
// Registers COM objects normally and registers VS Packages to the specified VS registry hive under HKCU
extern(Windows)
HRESULT VSDllRegisterServerUser(in wchar* strRegRoot)
@@ -637,80 +636,6 @@ version(none){
return S_OK;
}
-/*---------------------------------------------------------
- Registry helpers
------------------------------------------------------------*/
-HRESULT RegCreateValue(HKEY key, in wstring name, in wstring value)
-{
- wstring szName = name ~ cast(wchar)0;
- wstring szValue = value ~ cast(wchar)0;
- DWORD dwDataSize = value is null ? 0 : wchar.sizeof * (value.length+1);
- LONG lRetCode = RegSetValueExW(key, szName.ptr, 0, REG_SZ, cast(ubyte*)(szValue.ptr), dwDataSize);
- return HRESULT_FROM_WIN32(lRetCode);
-}
-
-HRESULT RegCreateDwordValue(HKEY key, in wstring name, in DWORD value)
-{
- wstring szName = name ~ cast(wchar)0;
- LONG lRetCode = RegSetValueExW(key, szName.ptr, 0, REG_DWORD, cast(ubyte*)(&value), value.sizeof);
- return HRESULT_FROM_WIN32(lRetCode);
-}
-
-HRESULT RegCreateQwordValue(HKEY key, in wstring name, in long value)
-{
- wstring szName = name ~ cast(wchar)0;
- LONG lRetCode = RegSetValueExW(key, szName.ptr, 0, REG_QWORD, cast(ubyte*)(&value), value.sizeof);
- return HRESULT_FROM_WIN32(lRetCode);
-}
-
-HRESULT RegCreateBinaryValue(HKEY key, in wstring name, in void[] data)
-{
- wstring szName = name ~ cast(wchar)0;
- LONG lRetCode = RegSetValueExW(key, szName.ptr, 0, REG_BINARY, cast(ubyte*)data.ptr, data.length);
- return HRESULT_FROM_WIN32(lRetCode);
-}
-
-HRESULT RegDeleteRecursive(HKEY keyRoot, wstring path)
-{
- HRESULT hr;
- HKEY key;
- ULONG subKeys = 0;
- ULONG maxKeyLen = 0;
- ULONG currentKey = 0;
- wstring[] keyNames;
-
- hr = hrRegOpenKeyEx(keyRoot, path, 0, (KEY_READ & SECURE_ACCESS), &key);
- if (!FAILED(hr))
- {
- LONG lRetCode = RegQueryInfoKeyW(key, null, null, null, &subKeys, &maxKeyLen,
- null, null, null, null, null, null);
- if (ERROR_SUCCESS != lRetCode)
- {
- hr = HRESULT_FROM_WIN32(lRetCode);
- }
- else if (subKeys > 0)
- {
- wchar[] keyName = new wchar[maxKeyLen+1];
- for (currentKey = 0; currentKey < subKeys; currentKey++)
- {
- ULONG keyLen = maxKeyLen+1;
- lRetCode = RegEnumKeyExW(key, currentKey, keyName.ptr, &keyLen, null, null, null, null);
- if (ERROR_SUCCESS == lRetCode)
- keyNames ~= to_wstring(keyName.ptr, keyLen);
- }
- foreach(wstring subkey; keyNames)
- RegDeleteRecursive(key, subkey);
- }
- }
-fail:
- wstring szPath = path ~ cast(wchar)0;
- LONG lRetCode = RegDeleteKeyW(keyRoot, szPath.ptr);
- if (SUCCEEDED(hr) && (ERROR_SUCCESS != lRetCode))
- hr = HRESULT_FROM_WIN32(lRetCode);
- if (key) RegCloseKey(key);
- return hr;
-}
-
wstring GetDLLName(HINSTANCE inst)
{
//get dll path
@@ -733,18 +658,3 @@ wstring GetTemplatePath(wstring dllpath)
return toUTF16(path);
}
-HRESULT hrRegOpenKeyEx(HKEY root, wstring regPath, int reserved, REGSAM samDesired, HKEY* phkResult)
-{
- wchar* szRegPath = _toUTF16zw(regPath);
- LONG lRes = RegOpenKeyExW(root, szRegPath, 0, samDesired, phkResult);
- return HRESULT_FROM_WIN32(lRes);
-}
-
-HRESULT hrRegCreateKeyEx(HKEY keySub, wstring regPath, int reserved, wstring classname, DWORD opt, DWORD samDesired,
- SECURITY_ATTRIBUTES* security, HKEY* key, DWORD* disposition)
-{
- wchar* szRegPath = _toUTF16zw(regPath);
- wchar* szClassname = _toUTF16zw(classname);
- LONG lRes = RegCreateKeyExW(keySub, szRegPath, 0, szClassname, opt, samDesired, security, key, disposition);
- return HRESULT_FROM_WIN32(lRes);
-}
diff --git a/visuald/visuald.visualdproj b/visuald/visuald.visualdproj
index db1c1c36..40df4c9f 100644
--- a/visuald/visuald.visualdproj
+++ b/visuald/visuald.visualdproj
@@ -12,6 +12,7 @@
0
0
0
+ 0
1
0
0
@@ -48,6 +49,8 @@
0
0
0
+ $(CC) -c
+ 1
m:\s\d\rainers\windows\bin\dmd_msc.exe
..
..;resources
@@ -109,6 +112,7 @@
0
0
0
+ 0
0
1
0
@@ -145,6 +149,8 @@
0
0
0
+ $(CC) -c
+ 1
m:\s\d\rainers\windows\bin\dmd.exe
..
..;resources
@@ -206,6 +212,7 @@
0
0
0
+ 0
0
1
0
@@ -242,6 +249,8 @@
0
0
0
+ $(CC) -c
+ 1
m:\s\d\rainers\windows\bin\dmd_msc.exe
..;m:\s\d\rainers\druntime\src
..;resources
@@ -303,6 +312,7 @@
0
0
0
+ 0
1
0
0
@@ -339,6 +349,8 @@
0
2
0
+ $(CC) -c
+ 1
m:\s\d\rainers\windows\bin\dmd_msc.exe
..
..;resources
@@ -400,6 +412,7 @@
0
0
0
+ 0
1
0
0
@@ -436,6 +449,8 @@
0
0
0
+ $(CC) -c
+ 1
m:\s\d\rainers\windows\bin\dmd_msc.exe
..
..;resources