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