diff --git a/CHANGES b/CHANGES index 5385db5a..3bcd9cde 100644 --- a/CHANGES +++ b/CHANGES @@ -594,6 +594,7 @@ unreleased Version 0.3.38 * updated to cv2pdb 0.28 - support mspdb120.dll from VS 2013 - bugzilla 11537: improved search for appropriate mspdb*.dll if multiple version of VS installed + - fix support for DWARF conversion for gcc 4.8 * updated to mago 0.9 - bugzilla 11547: remove error message when stopping debugging - bugzilla 11437: debug info rejected if records don't have "recommended" order @@ -613,4 +614,10 @@ unreleased Version 0.3.38 * Windows SDK 8.0/8.1 detection * fix bad "\n" in default x64 library search path * x64 executable and library search path not correctly saved for next VS start - * improve project automation to mute NuGet (still empty project pretended) \ No newline at end of file + * improve project automation to mute NuGet (still empty project pretended) + + * add source control support for git in VS2013 (and maybe others) + * fix DnD of project items in VS2013 + * disguise functionality of pipedmd.exe and filemonitor.dll to let it pass + most anti-virus checks + * added option to select the C runtime library when compiling for x64 diff --git a/TODO b/TODO index 5555941a..2fead580 100644 --- a/TODO +++ b/TODO @@ -39,6 +39,7 @@ Project: - custom command: quotes in dependencies not supported - VS2013: property pages don't follow resize - custom command: writes build batch to souce folder +- does not work with VS2013 git integration Language service: ----------------- @@ -148,3 +149,4 @@ Unsorted - save file before "Compile & run" - coverage line highlight after "Compile & run" doesn't update - better keeping track of line changes + diff --git a/VERSION b/VERSION index a4259afd..293637d4 100644 --- a/VERSION +++ b/VERSION @@ -2,4 +2,4 @@ #define VERSION_MINOR 3 #define VERSION_REVISION 38 #define VERSION_BETA -beta -#define VERSION_BUILD 3 +#define VERSION_BUILD 4 diff --git a/build/build.visualdproj b/build/build.visualdproj index 7d29b420..9bad42f2 100644 --- a/build/build.visualdproj +++ b/build/build.visualdproj @@ -185,7 +185,8 @@ 1 - echo Success >$(TargetPath) + echo Success >$(TargetPath) +echo. >$(TargetDir)\build.dep *.obj;*.cmd;*.build;*.json;*.dep @@ -194,7 +195,7 @@ if errorlevel 1 goto reportError call $(InputPath) "$(OutDir)\tlb2idl.exe" "$(OutDir)\dte_idl.success"" outfile="$(OutDir)\dte_idl.success" /> - + diff --git a/tools/filemonitor.d b/tools/filemonitor.d index 0584e8d4..2329e1b8 100644 --- a/tools/filemonitor.d +++ b/tools/filemonitor.d @@ -51,56 +51,67 @@ BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) g_hInst = hInstance; if(ulReason == DLL_PROCESS_ATTACH) { - RedirectCreateFileA(); - RedirectCreateFileW(); + if (dumpFile[0]) // only execute if it was injected by pipedmd + { + //origWriteFile = getWriteFileFunc(); + RedirectCreateFileA(); + RedirectCreateFileW(); + } } return true; } alias typeof(&CreateFileA) fnCreateFileA; alias typeof(&CreateFileW) fnCreateFileW; +alias typeof(&WriteFile) fnWriteFile; __gshared fnCreateFileA origCreateFileA; __gshared fnCreateFileW origCreateFileW; +__gshared fnWriteFile origWriteFile; + +__gshared fnCreateFileA myCF = &MyCreateFileA; alias typeof(&VirtualProtect) fnVirtualProtect; -void RedirectCreateFileA() +fnVirtualProtect getVirtualProtectFunc() { - version(msgbox) MessageBoxA(null, "RedirectCreateFileA", "filemonitor", MB_OK); - ubyte* jmpAdr = cast(ubyte*)&CreateFileA; - auto impTableEntry = cast(fnCreateFileA*) (*cast(void**)(jmpAdr + 2)); - origCreateFileA = *impTableEntry; - - DWORD oldProtect, newProtect; version(all) { - VirtualProtect(impTableEntry, (*impTableEntry).sizeof, PAGE_READWRITE, &oldProtect); - *impTableEntry = &MyCreateFileA; - VirtualProtect(impTableEntry, (*impTableEntry).sizeof, oldProtect, &newProtect); + HANDLE krnl = GetModuleHandleA("kernel32.dll"); + return cast(fnVirtualProtect) GetProcAddress(krnl, "VirtualProtect"); } else { - char[16] func; - char*p = func.ptr; - mixin({ - string s; - foreach(c; [ 'V','i','r','t','u','a','l','P','r','o','t','e','c','t' ]) - { s ~= "*p++ = '"; s ~= c; s ~= "';"; } - return s; - }()); - *p = 0; + return &VirtualProtect; + } +} +fnWriteFile getWriteFileFunc() +{ + version(all) + { HANDLE krnl = GetModuleHandleA("kernel32.dll"); - if(fnVirtualProtect fn = cast(fnVirtualProtect) GetProcAddress(krnl, func.ptr)) - { - DWORD oldProtect, newProtect; - fn(impTableEntry, (*impTableEntry).sizeof, PAGE_READWRITE, &oldProtect); - *impTableEntry = &MyCreateFileA; - fn(impTableEntry, (*impTableEntry).sizeof, oldProtect, &newProtect); - } + return cast(fnWriteFile) GetProcAddress(krnl, "WriteFile"); + } + else + { + return &WriteFile; } } +void RedirectCreateFileA() +{ + version(msgbox) MessageBoxA(null, "RedirectCreateFileA", "filemonitor", MB_OK); + ubyte* jmpAdr = cast(ubyte*)&CreateFileA; + auto impTableEntry = cast(fnCreateFileA*) (*cast(void**)(jmpAdr + 2)); + origCreateFileA = *impTableEntry; + + DWORD oldProtect, newProtect; + auto pfnVirtualProtect = getVirtualProtectFunc(); + pfnVirtualProtect(impTableEntry, (*impTableEntry).sizeof, PAGE_READWRITE, &oldProtect); + *impTableEntry = &MyCreateFileA; + pfnVirtualProtect(impTableEntry, (*impTableEntry).sizeof, oldProtect, &newProtect); +} + void RedirectCreateFileW() { version(msgbox) MessageBoxA(null, "RedirectCreateFileW", "filemonitor", MB_OK); @@ -109,12 +120,10 @@ void RedirectCreateFileW() origCreateFileW = *impTableEntry; DWORD oldProtect, newProtect; - version(all) - { - VirtualProtect(impTableEntry, (*impTableEntry).sizeof, PAGE_READWRITE, &oldProtect); - *impTableEntry = &MyCreateFileW; - VirtualProtect(impTableEntry, (*impTableEntry).sizeof, oldProtect, &newProtect); - } + auto pfnVirtualProtect = getVirtualProtectFunc(); + pfnVirtualProtect(impTableEntry, (*impTableEntry).sizeof, PAGE_READWRITE, &oldProtect); + *impTableEntry = &MyCreateFileW; + pfnVirtualProtect(impTableEntry, (*impTableEntry).sizeof, oldProtect, &newProtect); } extern(Windows) HANDLE @@ -146,8 +155,8 @@ MyCreateFileA( WaitForSingleObject(hndMutex, INFINITE); size_t length = mystrlen(lpFileName); - WriteFile(hndDumpFile, lpFileName, length, &length, null); - WriteFile(hndDumpFile, "\n".ptr, 1, &length, null); + origWriteFile(hndDumpFile, lpFileName, length, &length, null); + origWriteFile(hndDumpFile, "\n".ptr, 1, &length, null); if(hndMutex != INVALID_HANDLE_VALUE) ReleaseMutex(hndMutex); @@ -185,7 +194,7 @@ MyCreateFileW( ushort bom = 0xFEFF; size_t written; if(hndDumpFile != INVALID_HANDLE_VALUE) - WriteFile(hndDumpFile, &bom, 2, &written, null); + origWriteFile(hndDumpFile, &bom, 2, &written, null); if(hndMutex != INVALID_HANDLE_VALUE) ReleaseMutex(hndMutex); @@ -197,8 +206,8 @@ MyCreateFileW( WaitForSingleObject(hndMutex, INFINITE); size_t length = mystrlen(lpFileName); - WriteFile(hndDumpFile, lpFileName, 2*length, &length, null); - WriteFile(hndDumpFile, "\n".ptr, 2, &length, null); + origWriteFile(hndDumpFile, lpFileName, 2*length, &length, null); + origWriteFile(hndDumpFile, "\n".ptr, 2, &length, null); if(hndMutex != INVALID_HANDLE_VALUE) ReleaseMutex(hndMutex); @@ -239,6 +248,7 @@ size_t mystrlen(const(wchar)* str) nothrow ///////// shut up compiler generated GC info failing to link extern(C) { + __gshared int D10TypeInfo_i6__initZ; __gshared int D10TypeInfo_v6__initZ; __gshared int D16TypeInfo_Pointer6__vtblZ; __gshared int D17TypeInfo_Function6__vtblZ; diff --git a/tools/nostacktrace.d b/tools/nostacktrace.d new file mode 100644 index 00000000..e671d18f --- /dev/null +++ b/tools/nostacktrace.d @@ -0,0 +1,36 @@ +// replacement module to disable stack traces and avoid the default stacktrace code +// to be linked in + +module core.sys.windows.stacktrace; + +import core.sys.windows.windows; + +class StackTrace : Throwable.TraceInfo +{ +public: + this(size_t skip, CONTEXT* context) + { + } + int opApply(scope int delegate(ref const(char[])) dg) const + { + return 0; + } + int opApply(scope int delegate(ref size_t, ref const(char[])) dg) const + { + return 0; + } + override string toString() const + { + return null; + } + static ulong[] trace(size_t skip = 0, CONTEXT* context = null) + { + return null; + } + static char[][] resolve(const(ulong)[] addresses) + { + return []; + } +private: + ulong[] m_trace; +} diff --git a/tools/pipedmd.d b/tools/pipedmd.d index e5362240..e4fb376d 100644 --- a/tools/pipedmd.d +++ b/tools/pipedmd.d @@ -455,12 +455,13 @@ void InjectDLL(HANDLE hProcess, string depsfile) // copy path to other process auto wdll = to!wstring(dll) ~ cast(wchar)0; auto wdllRemote = VirtualAllocEx(hProcess, null, wdll.length * 2, MEM_COMMIT, PAGE_READWRITE); - WriteProcessMemory(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 = CreateRemoteThread(hProcess, null, 0, cast(LPTHREAD_START_ROUTINE)proc, wdllRemote, 0, null); + hThread = getCreateRemoteThreadFunc()(hProcess, null, 0, cast(LPTHREAD_START_ROUTINE)proc, wdllRemote, 0, null); WaitForSingleObject(hThread, INFINITE); // Get handle of the loaded module @@ -472,6 +473,19 @@ void InjectDLL(HANDLE hProcess, string depsfile) void* pDumpFile = cast(char*)hRemoteModule + 0x3000; // offset taken from map file auto szDepsFile = toMBSz(depsfile); - WriteProcessMemory(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; +} + +typeof(CreateRemoteThread)* getCreateRemoteThreadFunc () +{ + HMODULE mod = GetModuleHandleA("Kernel32"); + auto proc = GetProcAddress(mod, "CreateRemoteThread"); + return cast(typeof(CreateRemoteThread)*)proc; +} \ No newline at end of file diff --git a/vdc/abothe/VDServer.cs b/vdc/abothe/VDServer.cs index daeb83c5..a4f395d2 100644 --- a/vdc/abothe/VDServer.cs +++ b/vdc/abothe/VDServer.cs @@ -141,6 +141,11 @@ public void AddPackage(string packageName) addExpansion(packageName, "PKG", ""); } + public void AddCodeGeneratingNodeItem(INode node, string codeToGenerate) + { + addExpansion(codeToGenerate, "OVR", codeToGenerate); + } + void addExpansion(string name, string type, string desc) { if(!string.IsNullOrEmpty(name)) @@ -277,7 +282,7 @@ public static string GeneratePrototype(DMethod dm, bool isTemplateParamInsight=f foreach (var attr in dm.Attributes) { var m = attr as Modifier; - if (m != null && DTokens.StorageClass[m.Token]) + if (m != null && DTokens.IsStorageClass(m.Token)) { sb.Append(DTokens.GetTokenString(m.Token)); sb.Append(" "); diff --git a/visuald/automation.d b/visuald/automation.d new file mode 100644 index 00000000..ea07057e --- /dev/null +++ b/visuald/automation.d @@ -0,0 +1,1167 @@ +// This file is part of Visual D +// +// Visual D integrates the D programming language into Visual Studio +// Copyright (c) 2010-2014 by Rainer Schuetze, All Rights Reserved +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt + +module visuald.automation; + +import visuald.windows; +import std.path; + +import stdext.path; + +import sdk.vsi.vsshell; +import sdk.vsi.vsshell80; +import dte = sdk.vsi.dte80a; + +import visuald.comutil; +import visuald.logutil; +import visuald.dproject; +import visuald.dpackage; +import visuald.hierutil; +import visuald.chiernode; +import visuald.chiercontainer; +import visuald.pkgutil; + +enum HideProjectItems = true; + +class ExtProjectItem : DisposingDispatchObject, dte.ProjectItem +{ + this(ExtProject prj, ExtProjectItems parent, CHierNode node) + { + mExtProject = prj; + mParent = parent; + mNode = node; + } + + override void Dispose() + { + } + + override HRESULT QueryInterface(in IID* riid, void** pvObject) + { + if(queryInterface!(dte.ProjectItem) (this, riid, pvObject)) + return S_OK; + return super.QueryInterface(riid, pvObject); + } + + /+[id(0x0000000a), propget, hidden, helpstring("Returns value indicating whether object was changed since the last time it was saved."), helpcontext(0x0000eadb)]+/ + override HRESULT IsDirty(/+[out, retval]+/ VARIANT_BOOL* lpfReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x0000000a), propput, hidden, helpstring("Returns value indicating whether object was changed since the last time it was saved."), helpcontext(0x0000eadb)]+/ + override HRESULT IsDirty(in VARIANT_BOOL lpfReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x0000000b), propget, helpstring("Returns the full pathnames of the files associated with a project item."), helpcontext(0x0000eac9)]+/ + override HRESULT FileNames(in short index, + /+[out, retval]+/ BSTR* lpbstrReturn) + { + mixin(LogCallMix); + *lpbstrReturn = allocBSTR(mNode.GetFullPath()); + return S_OK; + } + + /+[id(0x0000000c), helpstring("Saves the project."), helpcontext(0x0000ea8f)]+/ + override HRESULT SaveAs(in BSTR NewFileName, + /+[out, retval]+/ VARIANT_BOOL* lpfReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x0000000d), propget, helpstring("Returns the number of files associated with the project item."), helpcontext(0x0000eac4)]+/ + override HRESULT FileCount(/+[out, retval]+/ short* lpsReturn) + { + *lpsReturn = 1; + return S_OK; + } + + /+[id(00000000), propget, helpstring("Sets/returns the name of the project."), helpcontext(0x0000eae9)]+/ + override HRESULT Name(/+[out, retval]+/ BSTR* pbstrReturn) + { + mixin(LogCallMix); + *pbstrReturn = allocBSTR(mNode.GetDisplayCaption()); + return S_OK; + } + + /+[id(00000000), propput, helpstring("Sets/returns the name of the project."), helpcontext(0x0000eae9)]+/ + override HRESULT Name(in BSTR pbstrReturn) + { + mixin(LogCallMix); + return S_FALSE; + } + + /+[id(0x00000036), propget, helpstring("Returns the collection containing the object supporting this property."), helpcontext(0x0000eab1)]+/ + override HRESULT Collection(/+[out, retval]+/ dte.ProjectItems * lppcReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x00000038), propget, helpstring("Returns the Properties collection."), helpcontext(0x0000eaf9)]+/ + override HRESULT Properties(/+[out, retval]+/ dte.Properties * ppObject) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x000000c8), propget, helpstring("Returns the top-level extensibility object."), helpcontext(0x0000eac1)]+/ + override HRESULT DTE(/+[out, retval]+/ dte.DTE * lppaReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x000000c9), propget, helpstring("Returns a GUID String indicating the kind or type of the object."), helpcontext(0x0000eadd)]+/ + override HRESULT Kind(/+[out, retval]+/ BSTR* lpbstrFileName) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x000000cb), propget, helpstring("Returns a ProjectItems collection for the object."), helpcontext(0x0000eaf6)]+/ + override HRESULT ProjectItems(/+[out, retval]+/ dte.ProjectItems * lppcReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x000000cc), propget, helpstring("Returns value indicating whether the ProjectItem is open for a particular view."), helpcontext(0x0000eadc)]+/ + override HRESULT IsOpen(/+[ optional , defaultvalue("{FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}")]+/ in BSTR ViewKind, + /+[out, retval]+/ VARIANT_BOOL* lpfReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x000000cd), helpstring("Opens the ProjectItem object in the specified view."), helpcontext(0x0000ea88)]+/ + override HRESULT Open(/+[ optional , defaultvalue("{00000000-0000-0000-0000-000000000000}")]+/ in BSTR ViewKind, + /+[out, retval]+/ dte.Window * lppfReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x000000ce), helpstring("Removes an object from a collection."), helpcontext(0x0000ea8c)]+/ + override HRESULT Remove() + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x0000006b), helpstring("Expands views of the project structure to show the ProjectItem."), helpcontext(0x0000ea7d)]+/ + override HRESULT ExpandView() + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x0000006c), propget, helpstring("Returns an interface or object that can be accessed at run time by name."), helpcontext(0x0000ea7f)]+/ + override HRESULT Object(/+[out, retval]+/ IDispatch * ProjectItemModel) + { + mixin(LogCallMix); + *ProjectItemModel = addref(this); + return S_OK; + } + + /+[id(0x0000006d), propget, helpstring("Get an Extender for this object under the specified category."), helpcontext(0x0000eb84)]+/ + override HRESULT Extender(in BSTR ExtenderName, + /+[out, retval]+/ IDispatch * Extender) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x0000006e), propget, helpstring("Get a list of available Extenders on this object."), helpcontext(0x0000eb85)]+/ + override HRESULT ExtenderNames(/+[out, retval]+/ VARIANT* ExtenderNames) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x0000006f), propget, helpstring("Get the Extension Category ID of this object."), helpcontext(0x0000eb86)]+/ + override HRESULT ExtenderCATID(/+[out, retval]+/ BSTR* pRetval) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x00000071), propget, helpstring("Returns value indicating whether object was changed since the last time it was saved."), helpcontext(0x0000eadb)]+/ + override HRESULT Saved(/+[out, retval]+/ VARIANT_BOOL* lpfReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x00000071), propput, helpstring("Returns value indicating whether object was changed since the last time it was saved."), helpcontext(0x0000eadb)]+/ + override HRESULT Saved(in VARIANT_BOOL lpfReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x00000074), propget, helpstring("Returns the ConfigurationManager object for this item."), helpcontext(0x0000ece9)]+/ + override HRESULT ConfigurationManager(/+[out, retval]+/ dte.ConfigurationManager * ppConfigurationManager) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x00000075), propget, helpstring("Returns the CodeModel object for this item."), helpcontext(0x0000ecea)]+/ + override HRESULT FileCodeModel(/+[out, retval]+/ dte.FileCodeModel * ppFileCodeModel) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x00000076), helpstring("Causes the item to be saved to storage."), helpcontext(0x0000ecfb)]+/ + override HRESULT Save(/+[optional, defaultvalue("")]+/ BSTR FileName) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x00000077), propget, helpstring("Returns the Document object for this item."), helpcontext(0x0000ecfc)]+/ + override HRESULT Document(/+[out, retval]+/ dte.Document * ppDocument) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x00000078), propget, helpstring("If the project item is the root of a sub-project, then returns the Project object for the sub-project."), helpcontext(0x0000ecfd)]+/ + override HRESULT SubProject(/+[out, retval]+/ dte.Project * ppProject) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x00000079), propget, helpstring("Returns the project that hosts this ProjectItem object."), helpcontext(0x0000ed1b)]+/ + override HRESULT ContainingProject(/+[out, retval]+/ dte.Project * ppProject) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x0000007a), helpstring("Removes the item from the project and it's storage."), helpcontext(0x0000ecfe)]+/ + override HRESULT Delete() + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + ////////////////////////////////////////////////////////////// + __gshared ComTypeInfoHolder mTypeHolder; + static void shared_static_this_typeHolder() + { + static class _ComTypeInfoHolder : ComTypeInfoHolder + { + override int GetIDsOfNames( + /* [size_is][in] */ in LPOLESTR *rgszNames, + /* [in] */ in UINT cNames, + /* [size_is][out] */ MEMBERID *pMemId) + { + //mixin(LogCallMix); + if (cNames == 1 && to_string(*rgszNames) == "Name") + { + *pMemId = 1; + return S_OK; + } + return returnError(E_NOTIMPL); + } + } + mTypeHolder = newCom!_ComTypeInfoHolder; + addref(mTypeHolder); + } + static void shared_static_dtor_typeHolder() + { + mTypeHolder = release(mTypeHolder); + } + + override ComTypeInfoHolder getTypeHolder () { return mTypeHolder; } + +private: + ExtProject mExtProject; + ExtProjectItems mParent; + CHierNode mNode; +}; + +class EmptyEnumerator : DComObject, IEnumVARIANT +{ + override HRESULT QueryInterface(in IID* riid, void** pvObject) + { + if(queryInterface!(IEnumVARIANT) (this, riid, pvObject)) + return S_OK; + return super.QueryInterface(riid, pvObject); + } + + HRESULT Next(in ULONG celt, + /+[out, size_is(celt), length_is(*pCeltFetched)]+/ VARIANT * rgVar, + /+[out]+/ ULONG * pCeltFetched) + { + if(pCeltFetched) + *pCeltFetched = 0; + return S_FALSE; + } + HRESULT Skip(in ULONG celt) + { + return S_OK; + } + HRESULT Reset() + { + return S_OK; + } + HRESULT Clone(/+[out]+/ IEnumVARIANT * ppEnum) + { + *ppEnum = addref(this); + return S_OK; + } +} + +class ProjectItemsEnumerator : DComObject, IEnumVARIANT +{ + this(ExtProjectItems item, CHierContainer node) + { + mItem = item; + mNode = node; + mCurrent = mNode.GetHead(); + } + + override HRESULT QueryInterface(in IID* riid, void** pvObject) + { + if(queryInterface!(IEnumVARIANT) (this, riid, pvObject)) + return S_OK; + return super.QueryInterface(riid, pvObject); + } + + HRESULT Next(in ULONG celt, + /+[out, size_is(celt), length_is(*pCeltFetched)]+/ VARIANT * rgVar, + /+[out]+/ ULONG * pCeltFetched) + { + if(!rgVar) + return E_INVALIDARG; + + ULONG c = 0; + for( ; mCurrent && c < celt; c++) + { + rgVar[c].vt = VT_UNKNOWN; + rgVar[c].punkVal = addref(newCom!ExtProjectItem(mItem.mExtProject, mItem, mCurrent)); + mCurrent = mCurrent.GetNext(); + } + if(pCeltFetched) + *pCeltFetched = c; + return c >= celt ? S_OK : S_FALSE; + } + HRESULT Skip(in ULONG celt) + { + foreach(_; 0 .. celt) + { + if(!mCurrent) + return S_FALSE; + mCurrent = mCurrent.GetNext(); + } + return S_OK; + } + HRESULT Reset() + { + mCurrent = mNode.GetHead(); + return S_OK; + } + HRESULT Clone(/+[out]+/ IEnumVARIANT * ppEnum) + { + *ppEnum = addref(newCom!ProjectItemsEnumerator(mItem, mNode)); + return S_OK; + } + + ExtProjectItems mItem; + CHierContainer mNode; + CHierNode mCurrent; +} + +class ProjectRootEnumerator : DComObject, IEnumVARIANT +{ + this(ExtProject prj) + { + mProject = prj; + mDone = false; + } + + override HRESULT QueryInterface(in IID* riid, void** pvObject) + { + if(queryInterface!(IEnumVARIANT) (this, riid, pvObject)) + return S_OK; + return super.QueryInterface(riid, pvObject); + } + + HRESULT Next(in ULONG celt, + /+[out, size_is(celt), length_is(*pCeltFetched)]+/ VARIANT * rgVar, + /+[out]+/ ULONG * pCeltFetched) + { + if(!rgVar) + return E_INVALIDARG; + + ULONG fetched = 0; + if(celt > 0 && !mDone) + { + rgVar.vt = VT_UNKNOWN; + rgVar.punkVal = addref(mProject); + mDone = true; + fetched = 1; + } + if(pCeltFetched) + *pCeltFetched = fetched; + return fetched >= celt ? S_OK : S_FALSE; + } + HRESULT Skip(in ULONG celt) + { + if(celt > 0) + mDone = true; + return !mDone ? S_OK : S_FALSE; + } + HRESULT Reset() + { + mDone = false; + return S_OK; + } + HRESULT Clone(/+[out]+/ IEnumVARIANT * ppEnum) + { + *ppEnum = addref(newCom!ProjectRootEnumerator(mProject)); + return S_OK; + } + + ExtProject mProject; + bool mDone; +} + +class ExtProjectItems : DisposingDispatchObject, dte.ProjectItems +{ + this(ExtProject prj, ExtProjectItems parent, CHierNode node) + { + mExtProject = prj; + mParent = parent; + mNode = node; + } + + __gshared ComTypeInfoHolder mTypeHolder; + + override ComTypeInfoHolder getTypeHolder () { return mTypeHolder; } + + override void Dispose() + { + } + + override HRESULT QueryInterface(in IID* riid, void** pvObject) + { + //mixin(LogCallMix); + + if(queryInterface!(dte.ProjectItems) (this, riid, pvObject)) + return S_OK; + return super.QueryInterface(riid, pvObject); + } + + override int Item( + /* [in] */ in VARIANT index, + /* [retval][out] */ dte.ProjectItem *lppcReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + override int Parent( + /* [retval][out] */ IDispatch* lppptReturn) + { + mixin(LogCallMix); + *lppptReturn = addref(mParent); + return S_OK; + } + + override int Count( + /* [retval][out] */ int *lplReturn) + { + logCall("%s.get_Count(lplReturn=%s)", this, lplReturn); + static if(HideProjectItems) + *lplReturn = 0; + else if(auto c = cast(CHierContainer) mNode) + *lplReturn = c.GetCount(); + else + *lplReturn = 0; + return S_OK; + } + + override int _NewEnum( + /* [retval][out] */ IUnknown *lppiuReturn) + { + mixin(LogCallMix); + static if(HideProjectItems) + *lppiuReturn = addref(newCom!EmptyEnumerator()); + else if(auto c = cast(CHierContainer) mNode) + *lppiuReturn = addref(newCom!ProjectItemsEnumerator(this, c)); + else + *lppiuReturn = addref(newCom!EmptyEnumerator()); + return S_OK; + } + + override int DTE( + /* [retval][out] */ dte.DTE *lppaReturn) + { + logCall("%s.get_DTE()", this); + return returnError(E_NOTIMPL); + } + + override int Kind( + /* [retval][out] */ BSTR *lpbstrFileName) + { + logCall("%s.get_Kind(lpbstrFileName=%s)", this, lpbstrFileName); + return returnError(E_NOTIMPL); + } + + override int AddFromFile( + /* [in] */ in BSTR FileName, + /* [retval][out] */ dte.ProjectItem *lppcReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + override int AddFromTemplate( + /* [in] */ in BSTR FileName, + /* [in] */ in BSTR Name, + /* [retval][out] */ dte.ProjectItem *lppcReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + override int AddFromDirectory( + /* [in] */ in BSTR Directory, + /* [retval][out] */ dte.ProjectItem *lppcReturn) + { + logCall("AddFromDirectory(Directory=%s, lppcReturn=%s)", _toLog(Directory), _toLog(lppcReturn)); + return returnError(E_NOTIMPL); + } + + override int ContainingProject( + /* [retval][out] */ dte.Project* ppProject) + { + mixin(LogCallMix); + *ppProject = addref(mExtProject); + return S_OK; + } + + override int AddFolder( + BSTR Name, + /* [defaultvalue] */ BSTR Kind, + /* [retval][out] */ dte.ProjectItem *pProjectItem) + { + logCall("AddFolder(Kind=%s, pProjectItem=%s)", _toLog(Kind), _toLog(pProjectItem)); + return returnError(E_NOTIMPL); + } + + override int AddFromFileCopy( + BSTR FilePath, + /* [retval][out] */ dte.ProjectItem *pProjectItem) + { + logCall("AddFromFileCopy(FilePath=%s, pProjectItem=%s)", _toLog(FilePath), _toLog(pProjectItem)); + return returnError(E_NOTIMPL); + } + + ExtProject mExtProject; + ExtProjectItems mParent; + CHierNode mNode; +}; + +class ExtProjectRootItems : ExtProjectItems +{ + this(ExtProject prj, ExtProjectItems parent, CHierNode node) + { + super(prj, parent, node); + } + + override int _NewEnum(/* [retval][out] */ IUnknown *lppiuReturn) + { + mixin(LogCallMix); + *lppiuReturn = addref(newCom!ProjectRootEnumerator(mExtProject)); + return S_OK; + } +} + +class ExtProperties : DisposingDispatchObject, dte.Properties +{ + this(ExtProject prj) + { + mProject = addref(prj); + } + + override void Dispose() + { + mProject = release(mProject); + } + + override HRESULT QueryInterface(in IID* riid, void** pvObject) + { + //mixin(LogCallMix); + + if(queryInterface!(dte.Properties) (this, riid, pvObject)) + return S_OK; + return super.QueryInterface(riid, pvObject); + } + + override HRESULT Item(in VARIANT index, dte.Property * lplppReturn) + { + mixin(LogCallMix); + if(index.vt != VT_BSTR) + return E_INVALIDARG; + + string prop = to_string(index.bstrVal); + if(prop == "FullPath") + { + string fullpath = mProject.mProject.GetFilename(); + *lplppReturn = addref(newCom!ExtProperty(this, prop, fullpath)); + return S_OK; + } + if(prop == "ProjectDirectory") + { + string fullpath = dirName(mProject.mProject.GetFilename()); + *lplppReturn = addref(newCom!ExtProperty(this, prop, fullpath)); + return S_OK; + } + return returnError(S_FALSE); + } + + /+[id(0x00000001), propget, restricted, hidden]+/ + override HRESULT Application(/+[out, retval]+/ IDispatch * lppidReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + /+[id(0x00000002), propget, helpstring("Returns the parent object."), helpcontext(0x0000eaf2)]+/ + override HRESULT Parent(/+[out, retval]+/ IDispatch * lppidReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + /+[id(0x00000028), propget, helpstring("Returns value indicating the count of objects in the collection."), helpcontext(0x0000eabb)]+/ + override HRESULT Count(/+[out, retval]+/ int* lplReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + /+[id(0xfffffffc), restricted]+/ + override HRESULT _NewEnum(/+[out, retval]+/ IUnknown * lppiuReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + /+[id(0x00000064), propget, helpstring("Returns the top-level extensibility object."), helpcontext(0x0000eac1)]+/ + override HRESULT DTE(/+[out, retval]+/ dte.DTE * lppaReturn) + { + mixin(LogCallMix); + return mProject.DTE(lppaReturn); + } + + ////////////////////////////////////////////////////////////// + __gshared ComTypeInfoHolder mTypeHolder; + static void shared_static_this_typeHolder() + { + static class _ComTypeInfoHolder : ComTypeInfoHolder + { + override int GetIDsOfNames( + /* [size_is][in] */ in LPOLESTR *rgszNames, + /* [in] */ in UINT cNames, + /* [size_is][out] */ MEMBERID *pMemId) + { + //mixin(LogCallMix); + if (cNames == 1 && to_string(*rgszNames) == "Name") + { + *pMemId = 1; + return S_OK; + } + return returnError(E_NOTIMPL); + } + } + mTypeHolder = newCom!_ComTypeInfoHolder; + addref(mTypeHolder); + } + static void shared_static_dtor_typeHolder() + { + mTypeHolder = release(mTypeHolder); + } + + override ComTypeInfoHolder getTypeHolder () { return mTypeHolder; } + +private: + ExtProject mProject; +} + +class ExtProperty : DisposingDispatchObject, dte.Property +{ + this(ExtProperties props, string name, string value) + { + mProperties = addref(props); + mName = name; + mValue = value; + } + + override void Dispose() + { + mProperties = release(mProperties); + } + + override HRESULT QueryInterface(in IID* riid, void** pvObject) + { + //mixin(LogCallMix); + + if(queryInterface!(dte.Property) (this, riid, pvObject)) + return S_OK; + return super.QueryInterface(riid, pvObject); + } + + HRESULT Value(/+[out, retval]+/ VARIANT* lppvReturn) + { + mixin(LogCallMix); + lppvReturn.vt = VT_BSTR; + lppvReturn.bstrVal = allocBSTR(mValue); + return S_OK; + } + + /+[id(00000000), propput, helpstring("Sets/ returns the value of property returned by the Property object."), helpcontext(0x0000eb08)]+/ + HRESULT Value(in VARIANT lppvReturn) + { + mixin(LogCallMix); + return returnError(S_FALSE); + } + + /+[id(00000000), propputref, helpstring("Sets/ returns the value of property returned by the Property object."), helpcontext(0x0000eb08)]+/ + HRESULT putref_Value(in VARIANT lppvReturn) + { + mixin(LogCallMix); + return returnError(S_FALSE); + } + + /+[id(0x00000003), propget, helpstring("Returns one element of a list."), helpcontext(0x0000ead6)]+/ + HRESULT IndexedValue(in VARIANT Index1, + /+[ optional]+/ in VARIANT Index2, + /+[ optional]+/ in VARIANT Index3, + /+[ optional]+/ in VARIANT Index4, + /+[out, retval]+/ VARIANT* Val) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x00000003), propput, helpstring("Returns one element of a list."), helpcontext(0x0000ead6)]+/ + HRESULT IndexedValue(in VARIANT Index1, + /+[ optional]+/ in VARIANT Index2, + /+[ optional]+/ in VARIANT Index3, + /+[ optional]+/ in VARIANT Index4, + in VARIANT Val) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x00000004), propget, helpstring("Returns a value representing the number of items in the list value."), helpcontext(0x0000eaea)]+/ + HRESULT NumIndices(/+[out, retval]+/ short* lpiRetVal) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x00000001), propget, restricted, hidden]+/ + HRESULT Application(/+[out, retval]+/ IDispatch * lppidReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x00000002), propget, restricted, hidden]+/ + HRESULT Parent(/+[out, retval]+/ dte.Properties * lpppReturn) + { + mixin(LogCallMix); + *lpppReturn = addref(mProperties); + return S_OK; + } + + /+[id(0x00000028), propget, helpstring("Returns the name of the object."), helpcontext(0x0000edbb)]+/ + HRESULT Name(/+[out, retval]+/ BSTR* lpbstrReturn) + { + mixin(LogCallMix); + *lpbstrReturn = allocBSTR(mName); + return S_OK; + } + + /+[id(0x0000002a), propget, helpstring("Returns the collection containing the object supporting this property."), helpcontext(0x0000eab1)]+/ + HRESULT Collection(/+[out, retval]+/ dte.Properties * lpppReturn) + { + mixin(LogCallMix); + *lpppReturn = addref(mProperties); + return S_OK; + } + + /+[id(0x0000002d), propget, helpstring("Sets/returns value of Property object when type of value is Object."), helpcontext(0x0000eaed)]+/ + HRESULT Object(/+[out, retval]+/ IDispatch * lppunk) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x0000002d), propputref, helpstring("Sets/returns value of Property object when type of value is Object."), helpcontext(0x0000eaed)]+/ + HRESULT Object(/+[in]+/ IUnknown lppunk) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + /+[id(0x00000064), propget, helpstring("Returns the top-level extensibility object."), helpcontext(0x0000eac1)]+/ + HRESULT DTE(/+[out, retval]+/ dte.DTE * lppaReturn) + { + mixin(LogCallMix); + return mProperties.DTE(lppaReturn); + } + + + ////////////////////////////////////////////////////////////// + __gshared ComTypeInfoHolder mTypeHolder; + static void shared_static_this_typeHolder() + { + static class _ComTypeInfoHolder : ComTypeInfoHolder + { + override int GetIDsOfNames( + /* [size_is][in] */ in LPOLESTR *rgszNames, + /* [in] */ in UINT cNames, + /* [size_is][out] */ MEMBERID *pMemId) + { + //mixin(LogCallMix); + if (cNames == 1 && to_string(*rgszNames) == "Name") + { + *pMemId = 1; + return S_OK; + } + return returnError(E_NOTIMPL); + } + } + mTypeHolder = newCom!_ComTypeInfoHolder; + addref(mTypeHolder); + } + static void shared_static_dtor_typeHolder() + { + mTypeHolder = release(mTypeHolder); + } + + override ComTypeInfoHolder getTypeHolder () { return mTypeHolder; } + +private: + string mName; + string mValue; + ExtProperties mProperties; +} + +class ExtProject : ExtProjectItem, dte.Project +{ + this(Project prj) + { + super(this, null, prj.GetProjectNode()); + mProject = prj; + mProperties = addref(newCom!ExtProperties(this)); + } + + override void Dispose() + { + mProperties = release(mProperties); + } + + override HRESULT QueryInterface(in IID* riid, void** pvObject) + { + //mixin(LogCallMix); + + if(queryInterface!(dte.Project) (this, riid, pvObject)) + return S_OK; + return super.QueryInterface(riid, pvObject); + } + + // DTE.Project + override int Name( + /* [retval][out] */ BSTR *lpbstrName) + { + logCall("%s.get_Name(lpbstrName=%s)", this, _toLog(lpbstrName)); + *lpbstrName = allocBSTR(mProject.GetCaption()); + return S_OK; + } + + override int Name( + /* [in] */ in BSTR bstrName) + { + logCall("%s.put_Name(bstrName=%s)", this, _toLog(bstrName)); + mProject.SetCaption(to_string(bstrName)); + return S_OK; + } + + override int FileName( + /* [retval][out] */ BSTR *lpbstrName) + { + logCall("%s.get_FileName(lpbstrName=%s)", this, _toLog(lpbstrName)); + *lpbstrName = allocBSTR(mProject.GetFilename()); + return S_OK; + } + + override int IsDirty( + /* [retval][out] */ VARIANT_BOOL *lpfReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + override int IsDirty( + /* [in] */ in VARIANT_BOOL Dirty) + { + logCall("%s.put_IsDirty(Dirty=%s)", this, _toLog(Dirty)); + return returnError(E_NOTIMPL); + } + + override int Collection( + /* [retval][out] */ dte.Projects *lppaReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + override int SaveAs( + /* [in] */ in BSTR NewFileName) + { + logCall("%s.SaveAs(NewFileName=%s)", this, _toLog(NewFileName)); + return returnError(E_NOTIMPL); + } + + override int DTE( + /* [retval][out] */ dte.DTE *lppaReturn) + { + logCall("%s.get_DTE()", this); + dte._DTE _dte = queryService!(dte._DTE); + if(!_dte) + return returnError(E_NOINTERFACE); + scope(exit) _dte.Release(); + return _dte.DTE(lppaReturn); + } + + override int Kind( + /* [retval][out] */ BSTR *lpbstrName) + { + logCall("%s.get_Kind(lpbstrName=%s)", this, _toLog(lpbstrName)); + wstring s = GUID2wstring(g_projectFactoryCLSID); + *lpbstrName = allocwBSTR(s); + return S_OK; + } + + override int ProjectItems( + /* [retval][out] */ dte.ProjectItems* lppcReturn) + { + mixin(LogCallMix); + *lppcReturn = addref(newCom!ExtProjectItems(this, null, mProject.GetProjectNode())); + return S_OK; + } + + override int Properties( + /* [retval][out] */ dte.Properties *ppObject) + { + mixin(LogCallMix); + *ppObject = addref(mProperties); + return S_OK; + } + + override int UniqueName( + /* [retval][out] */ BSTR *lpbstrName) + { + logCall("%s.get_UniqueName(lpbstrName=%s)", this, _toLog(lpbstrName)); + + if (!mProject) + return returnError(E_FAIL); + + IVsSolution srpSolution = queryService!(IVsSolution); + if(!srpSolution) + return returnError(E_FAIL); + + IVsHierarchy pIVsHierarchy = mProject; // ->GetIVsHierarchy(); + + int hr = srpSolution.GetUniqueNameOfProject(pIVsHierarchy, lpbstrName); + srpSolution.Release(); + + return hr; + } + + override int Object( + /* [retval][out] */ IDispatch* ProjectModel) + { + logCall("%s.get_Object(out ProjectModel=%s)", this, _toLog(&ProjectModel)); + *ProjectModel = addref(this); // (mProject); + return S_OK; + } + + override int Extender( + /* [in] */ in BSTR ExtenderName, + /* [retval][out] */ IDispatch *Extender) + { + logCall("%s.get_Extender(ExtenderName=%s)", this, _toLog(ExtenderName)); + return returnError(E_NOTIMPL); + } + + override int ExtenderNames( + /* [retval][out] */ VARIANT *ExtenderNames) + { + logCall("%s.get_ExtenderNames(ExtenderNames=%s)", this, _toLog(ExtenderNames)); + return returnError(E_NOTIMPL); + } + + override int ExtenderCATID( + /* [retval][out] */ BSTR *pRetval) + { + logCall("%s.get_ExtenderCATID(pRetval=%s)", this, _toLog(pRetval)); + return returnError(E_NOTIMPL); + } + + override int FullName( + /* [retval][out] */ BSTR *lpbstrName) + { + logCall("%s.get_FullName(lpbstrName=%s)", this, _toLog(lpbstrName)); + return FileName(lpbstrName); + } + + override int Saved( + /* [retval][out] */ VARIANT_BOOL *lpfReturn) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + override int Saved( + /* [in] */ in VARIANT_BOOL SavedFlag) + { + logCall("put_Saved(SavedFlag=%s)", _toLog(SavedFlag)); + return returnError(E_NOTIMPL); + } + + override int ConfigurationManager( + /* [retval][out] */ dte.ConfigurationManager* ppConfigurationManager) + { + mixin(LogCallMix); + + *ppConfigurationManager = mProject.getConfigurationManager(); + return S_OK; + } + + override int Globals( + /* [retval][out] */ dte.Globals* ppGlobals) + { + mixin(LogCallMix); + + HRESULT hr = S_OK; + // hr = CheckEnabledItem(this, &IID__DTE, L"Globals"); + // IfFailRet(hr); + + // if don't already have m_srpGlobals, get it from shell + IVsExtensibility3 ext = queryService!(dte.IVsExtensibility, IVsExtensibility3); + if(!ext) + return E_FAIL; + scope(exit) release(ext); + + dte.Globals globals; + VARIANT varIVsGlobalsCallback; + varIVsGlobalsCallback.vt = VT_UNKNOWN; + IVsHierarchy pIVsHierarchy = mProject; + hr = mProject.QueryInterface(&IID_IUnknown, cast(void**)&varIVsGlobalsCallback.punkVal); + if(!FAILED(hr)) + { + //! TODO fix: returns failure + hr = ext.GetGlobalsObject(varIVsGlobalsCallback, cast(IUnknown*) &globals); + varIVsGlobalsCallback.punkVal.Release(); + } + + *ppGlobals = globals; + return hr; + } + + override int Save( + /* [defaultvalue] */ BSTR FileName) + { + logCall("Save(FileName=%s)", _toLog(FileName)); + return returnError(E_NOTIMPL); + } + + override int ParentProjectItem( + /* [retval][out] */ dte.ProjectItem *ppParentProjectItem) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + override int CodeModel( + /* [retval][out] */ dte.CodeModel *ppCodeModel) + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + override int Delete() + { + mixin(LogCallMix); + return returnError(E_NOTIMPL); + } + + + ////////////////////////////////////////////////////////////// + __gshared ComTypeInfoHolder mTypeHolder; + static void shared_static_this_typeHolder() + { + static class _ComTypeInfoHolder : ComTypeInfoHolder + { + override int GetIDsOfNames( + /* [size_is][in] */ in LPOLESTR *rgszNames, + /* [in] */ in UINT cNames, + /* [size_is][out] */ MEMBERID *pMemId) + { + //mixin(LogCallMix); + if (cNames == 1 && to_string(*rgszNames) == "Name") + { + *pMemId = 1; + return S_OK; + } + return returnError(E_NOTIMPL); + } + } + mTypeHolder = newCom!_ComTypeInfoHolder; + addref(mTypeHolder); + } + static void shared_static_dtor_typeHolder() + { + mTypeHolder = release(mTypeHolder); + } + + override ComTypeInfoHolder getTypeHolder () { return mTypeHolder; } + + Project mProject; + dte.Properties mProperties; +} + +void automation_shared_static_this_typeHolder() +{ + ExtProjectItem.shared_static_this_typeHolder(); + ExtProperties.shared_static_this_typeHolder(); + ExtProperty.shared_static_this_typeHolder(); + ExtProject.shared_static_this_typeHolder(); +} + +void automation_shared_static_dtor_typeHolder() +{ + ExtProjectItem.shared_static_dtor_typeHolder(); + ExtProperties.shared_static_dtor_typeHolder(); + ExtProperty.shared_static_dtor_typeHolder(); + ExtProject.shared_static_dtor_typeHolder(); +} diff --git a/visuald/chiernode.d b/visuald/chiernode.d index ca0b1cb5..03002570 100644 --- a/visuald/chiernode.d +++ b/visuald/chiernode.d @@ -15,12 +15,14 @@ import std.utf; import sdk.vsi.vsshell; import sdk.vsi.vsshell80; +import sdk.vsi.ivssccmanager2; import visuald.hierarchy; import visuald.comutil; import visuald.logutil; import visuald.hierutil; import visuald.stringutil; +import visuald.automation; //import dproject; @@ -80,6 +82,7 @@ class CHierNode : DisposingDispatchObject override void Dispose() { + m_extNode = release(m_extNode); } static void setContainerIsSorted(bool sort) @@ -212,6 +215,15 @@ public: case VSHPROPID_StateIconIndex: pvar.vt = VT_I4; pvar.lVal = STATEICON_NOSTATEICON; + if(IVsSccManager2 sccmgr = queryService!(SVsSccManager, IVsSccManager2)()) + { + scope(exit) release(sccmgr); + auto path = _toUTF16z(GetFullPath()); + VsStateIcon icon; + DWORD sccStatus; + if(sccmgr.GetSccGlyph(1, &path, &icon, &sccStatus) == S_OK) + pvar.lVal = icon; + } return S_OK; case VSHPROPID_OverlayIconIndex: @@ -229,6 +241,18 @@ public: pvar.vt = VT_UNKNOWN; return QueryInterface(&IDispatch.iid, cast(void **)&pvar.pdispVal); + case VSHPROPID_ExtObject: + static if(!HideProjectItems) + { + pvar.vt = VT_DISPATCH; + if(!m_extNode) + m_extNode = addref(newCom!ExtProjectItem(null, null, this)); + pvar.pdispVal = addref(m_extNode); + return S_OK; + } + else + break; + default: break; } @@ -550,6 +574,7 @@ protected: CHierContainer m_pNodeParent; CHierNode m_pNodeNext; // to form a singly-linked list string m_strName; // this node's name + ExtProjectItem m_extNode; uint m_grfStateFlags; // ChildrenEnumerated, etc enum // m_grfStateFlags diff --git a/visuald/completion.d b/visuald/completion.d index 3fb8a564..fbedfcf3 100644 --- a/visuald/completion.d +++ b/visuald/completion.d @@ -147,6 +147,7 @@ class Declarations case "EVAL": return CSIMG_ENUMMEMBER; case "NMIX": return CSIMG_UNKNOWN2; case "VAR": return CSIMG_FIELD; + case "OVR": return CSIMG_UNKNOWN3; default: return 0; } } diff --git a/visuald/config.d b/visuald/config.d index eb398f07..a011f9e6 100644 --- a/visuald/config.d +++ b/visuald/config.d @@ -106,6 +106,15 @@ enum Subsystem Posix }; +enum CRuntime +{ + None, + StaticRelease, + StaticDebug, + DynamicRelease, + DynamicDebug, +} + class ProjectOptions { bool obj; // write object file @@ -218,7 +227,8 @@ class ProjectOptions string deffile; string resfile; string exefile; - bool useStdLibPath; + bool useStdLibPath; + uint cRuntime; string additionalOptions; string preBuildCommand; @@ -248,7 +258,8 @@ class ProjectOptions xfilename = "$(IntDir)\\$(TargetName).json"; doXGeneration = true; useStdLibPath = true; - + cRuntime = CRuntime.StaticRelease; + filesToClean = "*.obj;*.cmd;*.build;*.json;*.dep"; setDebug(dbg); setX64(x64); @@ -786,7 +797,10 @@ class ProjectOptions if(useStdLibPath) lpaths ~= tokenizeArgs(isX86_64 ? compilerDirectories.LibSearchPath64 : compilerDirectories.LibSearchPath); foreach(lp; lpaths) - cmd ~= (mslink ? " /LIBPATH:" : "+") ~ quoteFilename(normalizeDir(unquoteArgument(lp))); + if(mslink) + cmd ~= " /LIBPATH:" ~ quoteFilename(normalizeDir(unquoteArgument(lp))[0..$-1]); // avoid trailing \ for quoted files + else + cmd ~= "+" ~ quoteFilename(normalizeDir(unquoteArgument(lp))); // optlink needs trailing \ string def = deffile.length ? quoteNormalizeFilename(deffile) : plusList(lnkfiles, ".def", mslink ? " /DEF:" : plus); string res = resfile.length ? quoteNormalizeFilename(resfile) : plusList(lnkfiles, ".res", plus); @@ -821,6 +835,19 @@ class ProjectOptions cmd ~= mslink ? " /DEBUG" : "/CO"; cmd ~= mslink ? " /INCREMENTAL:NO /NOLOGO" : "/NOI"; + if(mslink) + { + switch(cRuntime) + { + case CRuntime.None: cmd ~= " /NODEFAULTLIB:libcmt"; break; + case CRuntime.StaticRelease: break; + case CRuntime.StaticDebug: cmd ~= " /NODEFAULTLIB:libcmt libcmtd.lib"; break; + case CRuntime.DynamicRelease: cmd ~= " /NODEFAULTLIB:libcmt msvcrt.lib"; break; + case CRuntime.DynamicDebug: cmd ~= " /NODEFAULTLIB:libcmt msvcrtd.lib"; break; + default: break; + } + } + if(lib != OutputType.StaticLib) { if(createImplib) @@ -1099,6 +1126,7 @@ class ProjectOptions elem ~= new xml.Element("resfile", toElem(resfile)); elem ~= new xml.Element("exefile", toElem(exefile)); elem ~= new xml.Element("useStdLibPath", toElem(useStdLibPath)); + elem ~= new xml.Element("cRuntime", toElem(cRuntime)); elem ~= new xml.Element("additionalOptions", toElem(additionalOptions)); elem ~= new xml.Element("preBuildCommand", toElem(preBuildCommand)); @@ -1221,6 +1249,7 @@ class ProjectOptions fromElem(elem, "resfile", resfile); fromElem(elem, "exefile", exefile); fromElem(elem, "useStdLibPath", useStdLibPath); + fromElem(elem, "cRuntime", cRuntime); fromElem(elem, "additionalOptions", additionalOptions); fromElem(elem, "preBuildCommand", preBuildCommand); @@ -2895,6 +2924,36 @@ class Config : DisposingComObject, { scope(exit) release(prjcfg); + debug logOutputGroups(prjcfg); + + version(none) + if(auto prjcfg2 = qi_cast!IVsProjectCfg2(prjcfg)) + { + scope(exit) release(prjcfg2); + IVsOutputGroup outputGroup; + if(prjcfg2.OpenOutputGroup(VS_OUTPUTGROUP_CNAME_Built, &outputGroup) == S_OK) + { + scope(exit) release(outputGroup); + ULONG cnt; + if(outputGroup.get_Outputs(0, null, &cnt) == S_OK) + { + auto outs = new IVsOutput2[cnt]; + if(outputGroup.get_Outputs(cnt, outs.ptr, null) == S_OK) + { + foreach(o; outs) + { + ScopedBSTR target; + if(o.get_CanonicalName(&target.bstr) == S_OK) + { + string targ = target.detach(); + libs ~= targ; + } + release(o); + } + } + } + } + } IVsEnumOutputs eo; if(prjcfg.EnumOutputs(&eo) == S_OK) { @@ -2921,6 +2980,54 @@ class Config : DisposingComObject, return libs; } + void logOutputGroups(IVsProjectCfg prjcfg) + { + if(auto prjcfg2 = qi_cast!IVsProjectCfg2(prjcfg)) + { + scope(exit) release(prjcfg2); + + ULONG cntGroups; + if(SUCCEEDED(prjcfg2.get_OutputGroups(0, null, &cntGroups))) + { + auto groups = new IVsOutputGroup[cntGroups]; + if(prjcfg2.get_OutputGroups(cntGroups, groups.ptr, &cntGroups) == S_OK) + { + foreach(outputGroup; groups) + { + scope(exit) release(outputGroup); + + BSTR bstrCanName, bstrDispName, bstrKeyOut, bstrDesc; + outputGroup.get_CanonicalName(&bstrCanName); + outputGroup.get_DisplayName(&bstrDispName); + outputGroup.get_KeyOutput(&bstrKeyOut); + outputGroup.get_Description(&bstrDesc); + + logCall("Group: %s Disp: %s KeyOut: %s Desc: %s", detachBSTR(bstrCanName), detachBSTR(bstrDispName), detachBSTR(bstrKeyOut), detachBSTR(bstrDesc)); + + ULONG cnt; + if(outputGroup.get_Outputs(0, null, &cnt) == S_OK) + { + auto outs = new IVsOutput2[cnt]; + if(outputGroup.get_Outputs(cnt, outs.ptr, &cnt) == S_OK) + { + foreach(o; outs) + { + BSTR target, display, url; + o.get_CanonicalName(&target); + o.get_DisplayName(&display); + o.get_DeploySourceURL(&url); + logCall(" Out: %s Disp: %s URL: %s", detachBSTR(target), detachBSTR(display), detachBSTR(url)); + + release(o); + } + } + } + } + } + } + } + } + int addJSONFiles(ref string[] files) { int cnt = 0; diff --git a/visuald/dllmain.d b/visuald/dllmain.d index 699ca0c2..cb13571a 100644 --- a/visuald/dllmain.d +++ b/visuald/dllmain.d @@ -73,63 +73,6 @@ else // !version(TESTMAIN) { } // !version(D_Version2) -extern extern(C) __gshared ModuleInfo D4core3sys7windows10stacktrace12__ModuleInfoZ; - -void disableStacktrace() -{ - ModuleInfo* info = &D4core3sys7windows10stacktrace12__ModuleInfoZ; -static if(__traits(compiles,info.isNew)) -{ - // dmd 2.063 - if (info.isNew) - { - enum - { - MItlsctor = 8, - MItlsdtor = 0x10, - MIctor = 0x20, - MIdtor = 0x40, - MIxgetMembers = 0x80, - } - if (info.n.flags & MIctor) - { - size_t off = info.New.sizeof; - if (info.n.flags & MItlsctor) - off += info.o.tlsctor.sizeof; - if (info.n.flags & MItlsdtor) - off += info.o.tlsdtor.sizeof; - if (info.n.flags & MIxgetMembers) - off += info.o.xgetMembers.sizeof; - *cast(typeof(info.o.ctor)*)(cast(void*)info + off) = null; - } - } - else - info.o.ctor = null; -} -else -{ - // dmd 2.064alpha - enum - { - MItlsctor = 8, - MItlsdtor = 0x10, - MIctor = 0x20, - MIdtor = 0x40, - MIxgetMembers = 0x80, - } - if (info.flags & MIctor) - { - size_t off = info.sizeof; - if (info.flags & MItlsctor) - off += info.tlsctor.sizeof; - if (info.flags & MItlsdtor) - off += info.tlsdtor.sizeof; - if (info.flags & MIxgetMembers) - off += info.xgetMembers.sizeof; - *cast(typeof(info.ctor)*)(cast(void*)info + off) = null; - } -} -} void clearStack() { @@ -145,7 +88,6 @@ BOOL DllMain(stdwin.HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) { case DLL_PROCESS_ATTACH: //MessageBoxA(cast(HANDLE)0, "Hi", "there", 0); - disableStacktrace(); if(!dll_process_attach(hInstance, true)) return false; g_hInst = cast(HINSTANCE) hInstance; diff --git a/visuald/dpackage.d b/visuald/dpackage.d index a2554c85..cc1baa9d 100644 --- a/visuald/dpackage.d +++ b/visuald/dpackage.d @@ -29,6 +29,7 @@ import visuald.hierutil; import visuald.stringutil; import visuald.fileutil; import visuald.dproject; +import visuald.automation; import visuald.config; import visuald.chiernode; import visuald.dlangsvc; @@ -132,7 +133,7 @@ void global_init() LanguageService.shared_static_this(); CHierNode.shared_static_this(); CHierNode.shared_static_this_typeHolder(); - ExtProject.shared_static_this_typeHolder(); + automation_shared_static_this_typeHolder(); Project.shared_static_this_typeHolder(); } @@ -140,7 +141,7 @@ void global_exit() { LanguageService.shared_static_dtor(); CHierNode.shared_static_dtor_typeHolder(); - ExtProject.shared_static_dtor_typeHolder(); + automation_shared_static_dtor_typeHolder(); Project.shared_static_dtor_typeHolder(); Package.s_instance = null; } diff --git a/visuald/dproject.d b/visuald/dproject.d index 933a0d49..c36015e7 100644 --- a/visuald/dproject.d +++ b/visuald/dproject.d @@ -23,6 +23,8 @@ import stdext.path; import xml = visuald.xmlwrap; import sdk.win32.rpcdce; +import sdk.win32.oleauto; +import sdk.win32.objbase; import sdk.vsi.vsshell; import sdk.vsi.vsshell80; import sdk.vsi.vsshell90; @@ -32,6 +34,7 @@ import dte = sdk.vsi.dte80a; import visuald.comutil; import visuald.logutil; +import visuald.automation; import visuald.dpackage; import visuald.propertypage; import visuald.hierarchy; @@ -181,720 +184,6 @@ private: //Package mPackage; } -class EmptyEnumerator : DComObject, IEnumVARIANT -{ - override HRESULT QueryInterface(in IID* riid, void** pvObject) - { - if(queryInterface!(IEnumVARIANT) (this, riid, pvObject)) - return S_OK; - return super.QueryInterface(riid, pvObject); - } - - HRESULT Next(in ULONG celt, - /+[out, size_is(celt), length_is(*pCeltFetched)]+/ VARIANT * rgVar, - /+[out]+/ ULONG * pCeltFetched) - { - if(pCeltFetched) - *pCeltFetched = 0; - return S_FALSE; - } - HRESULT Skip(in ULONG celt) - { - return S_OK; - } - HRESULT Reset() - { - return S_OK; - } - HRESULT Clone(/+[out]+/ IEnumVARIANT * ppEnum) - { - *ppEnum = addref(this); - return S_OK; - } -} - -class ExtProjectItems : DisposingDispatchObject, dte.ProjectItems -{ - this(ExtProject prj) - { - mExtProject = prj; - } - - __gshared ComTypeInfoHolder mTypeHolder; - - override ComTypeInfoHolder getTypeHolder () { return mTypeHolder; } - - override void Dispose() - { - } - - override HRESULT QueryInterface(in IID* riid, void** pvObject) - { - //mixin(LogCallMix); - - if(queryInterface!(dte.ProjectItems) (this, riid, pvObject)) - return S_OK; - return super.QueryInterface(riid, pvObject); - } - - override int Item( - /* [in] */ in VARIANT index, - /* [retval][out] */ dte.ProjectItem *lppcReturn) - { - mixin(LogCallMix); - return returnError(E_NOTIMPL); - } - - override int Parent( - /* [retval][out] */ IDispatch* lppptReturn) - { - mixin(LogCallMix); - *lppptReturn = addref(mExtProject); - return S_OK; - } - - override int Count( - /* [retval][out] */ int *lplReturn) - { - logCall("%s.get_Count(lplReturn=%s)", this, lplReturn); - *lplReturn = 0; - return S_OK; - } - - override int _NewEnum( - /* [retval][out] */ IUnknown *lppiuReturn) - { - mixin(LogCallMix); - *lppiuReturn = addref(newCom!EmptyEnumerator()); - return S_OK; - } - - override int DTE( - /* [retval][out] */ dte.DTE *lppaReturn) - { - logCall("%s.get_DTE()", this); - return returnError(E_NOTIMPL); - } - - override int Kind( - /* [retval][out] */ BSTR *lpbstrFileName) - { - logCall("%s.get_Kind(lpbstrFileName=%s)", this, lpbstrFileName); - return returnError(E_NOTIMPL); - } - - override int AddFromFile( - /* [in] */ in BSTR FileName, - /* [retval][out] */ dte.ProjectItem *lppcReturn) - { - mixin(LogCallMix); - return returnError(E_NOTIMPL); - } - - override int AddFromTemplate( - /* [in] */ in BSTR FileName, - /* [in] */ in BSTR Name, - /* [retval][out] */ dte.ProjectItem *lppcReturn) - { - mixin(LogCallMix); - return returnError(E_NOTIMPL); - } - - override int AddFromDirectory( - /* [in] */ in BSTR Directory, - /* [retval][out] */ dte.ProjectItem *lppcReturn) - { - logCall("AddFromDirectory(Directory=%s, lppcReturn=%s)", _toLog(Directory), _toLog(lppcReturn)); - return returnError(E_NOTIMPL); - } - - override int ContainingProject( - /* [retval][out] */ dte.Project* ppProject) - { - mixin(LogCallMix); - *ppProject = addref(mExtProject); - return S_OK; - } - - override int AddFolder( - BSTR Name, - /* [defaultvalue] */ BSTR Kind, - /* [retval][out] */ dte.ProjectItem *pProjectItem) - { - logCall("AddFolder(Kind=%s, pProjectItem=%s)", _toLog(Kind), _toLog(pProjectItem)); - return returnError(E_NOTIMPL); - } - - override int AddFromFileCopy( - BSTR FilePath, - /* [retval][out] */ dte.ProjectItem *pProjectItem) - { - logCall("AddFromFileCopy(FilePath=%s, pProjectItem=%s)", _toLog(FilePath), _toLog(pProjectItem)); - return returnError(E_NOTIMPL); - } - - ExtProject mExtProject; -}; - - -class ExtProperties : DisposingDispatchObject, dte.Properties -{ - this(ExtProject prj) - { - mProject = addref(prj); - } - - override void Dispose() - { - mProject = release(mProject); - } - - override HRESULT QueryInterface(in IID* riid, void** pvObject) - { - //mixin(LogCallMix); - - if(queryInterface!(dte.Properties) (this, riid, pvObject)) - return S_OK; - return super.QueryInterface(riid, pvObject); - } - - override HRESULT Item(in VARIANT index, dte.Property * lplppReturn) - { - mixin(LogCallMix); - if(index.vt != VT_BSTR) - return E_INVALIDARG; - - string prop = to_string(index.bstrVal); - if(prop == "FullPath") - { - string fullpath = mProject.mProject.mFilename; - *lplppReturn = addref(newCom!ExtProperty(this, prop, fullpath)); - return S_OK; - } - if(prop == "ProjectDirectory") - { - string fullpath = dirName(mProject.mProject.mFilename); - *lplppReturn = addref(newCom!ExtProperty(this, prop, fullpath)); - return S_OK; - } - return returnError(E_NOTIMPL); - } - - /+[id(0x00000001), propget, restricted, hidden]+/ - override HRESULT Application(/+[out, retval]+/ IDispatch * lppidReturn) - { - mixin(LogCallMix); - return returnError(E_NOTIMPL); - } - /+[id(0x00000002), propget, helpstring("Returns the parent object."), helpcontext(0x0000eaf2)]+/ - override HRESULT Parent(/+[out, retval]+/ IDispatch * lppidReturn) - { - mixin(LogCallMix); - return returnError(E_NOTIMPL); - } - /+[id(0x00000028), propget, helpstring("Returns value indicating the count of objects in the collection."), helpcontext(0x0000eabb)]+/ - override HRESULT Count(/+[out, retval]+/ int* lplReturn) - { - mixin(LogCallMix); - return returnError(E_NOTIMPL); - } - /+[id(0xfffffffc), restricted]+/ - override HRESULT _NewEnum(/+[out, retval]+/ IUnknown * lppiuReturn) - { - mixin(LogCallMix); - return returnError(E_NOTIMPL); - } - /+[id(0x00000064), propget, helpstring("Returns the top-level extensibility object."), helpcontext(0x0000eac1)]+/ - override HRESULT DTE(/+[out, retval]+/ dte.DTE * lppaReturn) - { - mixin(LogCallMix); - return mProject.DTE(lppaReturn); - } - - ////////////////////////////////////////////////////////////// - __gshared ComTypeInfoHolder mTypeHolder; - static void shared_static_this_typeHolder() - { - static class _ComTypeInfoHolder : ComTypeInfoHolder - { - override int GetIDsOfNames( - /* [size_is][in] */ in LPOLESTR *rgszNames, - /* [in] */ in UINT cNames, - /* [size_is][out] */ MEMBERID *pMemId) - { - //mixin(LogCallMix); - if (cNames == 1 && to_string(*rgszNames) == "Name") - { - *pMemId = 1; - return S_OK; - } - return returnError(E_NOTIMPL); - } - } - mTypeHolder = newCom!_ComTypeInfoHolder; - addref(mTypeHolder); - } - static void shared_static_dtor_typeHolder() - { - mTypeHolder = release(mTypeHolder); - } - - override ComTypeInfoHolder getTypeHolder () { return mTypeHolder; } - -private: - ExtProject mProject; -} - -class ExtProperty : DisposingDispatchObject, dte.Property -{ - this(ExtProperties props, string name, string value) - { - mProperties = addref(props); - mName = name; - mValue = value; - } - - override void Dispose() - { - mProperties = release(mProperties); - } - - override HRESULT QueryInterface(in IID* riid, void** pvObject) - { - //mixin(LogCallMix); - - if(queryInterface!(dte.Property) (this, riid, pvObject)) - return S_OK; - return super.QueryInterface(riid, pvObject); - } - - HRESULT Value(/+[out, retval]+/ VARIANT* lppvReturn) - { - mixin(LogCallMix); - lppvReturn.vt = VT_BSTR; - lppvReturn.bstrVal = allocBSTR(mValue); - return S_OK; - } - - /+[id(00000000), propput, helpstring("Sets/ returns the value of property returned by the Property object."), helpcontext(0x0000eb08)]+/ - HRESULT Value(in VARIANT lppvReturn) - { - mixin(LogCallMix); - return returnError(S_FALSE); - } - - /+[id(00000000), propputref, helpstring("Sets/ returns the value of property returned by the Property object."), helpcontext(0x0000eb08)]+/ - HRESULT putref_Value(in VARIANT lppvReturn) - { - mixin(LogCallMix); - return returnError(S_FALSE); - } - - /+[id(0x00000003), propget, helpstring("Returns one element of a list."), helpcontext(0x0000ead6)]+/ - HRESULT IndexedValue(in VARIANT Index1, - /+[ optional]+/ in VARIANT Index2, - /+[ optional]+/ in VARIANT Index3, - /+[ optional]+/ in VARIANT Index4, - /+[out, retval]+/ VARIANT* Val) - { - mixin(LogCallMix); - return returnError(E_NOTIMPL); - } - - /+[id(0x00000003), propput, helpstring("Returns one element of a list."), helpcontext(0x0000ead6)]+/ - HRESULT IndexedValue(in VARIANT Index1, - /+[ optional]+/ in VARIANT Index2, - /+[ optional]+/ in VARIANT Index3, - /+[ optional]+/ in VARIANT Index4, - in VARIANT Val) - { - mixin(LogCallMix); - return returnError(E_NOTIMPL); - } - - /+[id(0x00000004), propget, helpstring("Returns a value representing the number of items in the list value."), helpcontext(0x0000eaea)]+/ - HRESULT NumIndices(/+[out, retval]+/ short* lpiRetVal) - { - mixin(LogCallMix); - return returnError(E_NOTIMPL); - } - - /+[id(0x00000001), propget, restricted, hidden]+/ - HRESULT Application(/+[out, retval]+/ IDispatch * lppidReturn) - { - mixin(LogCallMix); - return returnError(E_NOTIMPL); - } - - /+[id(0x00000002), propget, restricted, hidden]+/ - HRESULT Parent(/+[out, retval]+/ dte.Properties * lpppReturn) - { - mixin(LogCallMix); - *lpppReturn = addref(mProperties); - return S_OK; - } - - /+[id(0x00000028), propget, helpstring("Returns the name of the object."), helpcontext(0x0000edbb)]+/ - HRESULT Name(/+[out, retval]+/ BSTR* lpbstrReturn) - { - mixin(LogCallMix); - *lpbstrReturn = allocBSTR(mName); - return S_OK; - } - - /+[id(0x0000002a), propget, helpstring("Returns the collection containing the object supporting this property."), helpcontext(0x0000eab1)]+/ - HRESULT Collection(/+[out, retval]+/ dte.Properties * lpppReturn) - { - mixin(LogCallMix); - *lpppReturn = addref(mProperties); - return S_OK; - } - - /+[id(0x0000002d), propget, helpstring("Sets/returns value of Property object when type of value is Object."), helpcontext(0x0000eaed)]+/ - HRESULT Object(/+[out, retval]+/ IDispatch * lppunk) - { - mixin(LogCallMix); - return returnError(E_NOTIMPL); - } - - /+[id(0x0000002d), propputref, helpstring("Sets/returns value of Property object when type of value is Object."), helpcontext(0x0000eaed)]+/ - HRESULT Object(/+[in]+/ IUnknown lppunk) - { - mixin(LogCallMix); - return returnError(E_NOTIMPL); - } - - /+[id(0x00000064), propget, helpstring("Returns the top-level extensibility object."), helpcontext(0x0000eac1)]+/ - HRESULT DTE(/+[out, retval]+/ dte.DTE * lppaReturn) - { - mixin(LogCallMix); - return mProperties.DTE(lppaReturn); - } - - - ////////////////////////////////////////////////////////////// - __gshared ComTypeInfoHolder mTypeHolder; - static void shared_static_this_typeHolder() - { - static class _ComTypeInfoHolder : ComTypeInfoHolder - { - override int GetIDsOfNames( - /* [size_is][in] */ in LPOLESTR *rgszNames, - /* [in] */ in UINT cNames, - /* [size_is][out] */ MEMBERID *pMemId) - { - //mixin(LogCallMix); - if (cNames == 1 && to_string(*rgszNames) == "Name") - { - *pMemId = 1; - return S_OK; - } - return returnError(E_NOTIMPL); - } - } - mTypeHolder = newCom!_ComTypeInfoHolder; - addref(mTypeHolder); - } - static void shared_static_dtor_typeHolder() - { - mTypeHolder = release(mTypeHolder); - } - - override ComTypeInfoHolder getTypeHolder () { return mTypeHolder; } - -private: - string mName; - string mValue; - ExtProperties mProperties; -} - -class ExtProject : DisposingDispatchObject, dte.Project -{ - this(Project prj) - { - mProject = prj; - mProjectItems = addref(newCom!ExtProjectItems(this)); - mProperties = addref(newCom!ExtProperties(this)); - } - - override void Dispose() - { - mProjectItems = release(mProjectItems); - mProperties = release(mProperties); - } - - override HRESULT QueryInterface(in IID* riid, void** pvObject) - { - //mixin(LogCallMix); - - if(queryInterface!(dte.Project) (this, riid, pvObject)) - return S_OK; - return super.QueryInterface(riid, pvObject); - } - - // DTE.Project - override int Name( - /* [retval][out] */ BSTR *lpbstrName) - { - logCall("get_Name(lpbstrName=%s)", _toLog(lpbstrName)); - *lpbstrName = allocBSTR(mProject.mCaption); - return S_OK; - } - - override int Name( - /* [in] */ in BSTR bstrName) - { - logCall("put_Name(bstrName=%s)", _toLog(bstrName)); - mProject.mCaption = to_string(bstrName); - return S_OK; - } - - override int FileName( - /* [retval][out] */ BSTR *lpbstrName) - { - logCall("get_FileName(lpbstrName=%s)", _toLog(lpbstrName)); - *lpbstrName = allocBSTR(mProject.mFilename); - return S_OK; - } - - override int IsDirty( - /* [retval][out] */ VARIANT_BOOL *lpfReturn) - { - mixin(LogCallMix); - return returnError(E_NOTIMPL); - } - - override int IsDirty( - /* [in] */ in VARIANT_BOOL Dirty) - { - logCall("put_IsDirty(Dirty=%s)", _toLog(Dirty)); - return returnError(E_NOTIMPL); - } - - override int Collection( - /* [retval][out] */ dte.Projects *lppaReturn) - { - mixin(LogCallMix); - return returnError(E_NOTIMPL); - } - - override int SaveAs( - /* [in] */ in BSTR NewFileName) - { - logCall("SaveAs(NewFileName=%s)", _toLog(NewFileName)); - return returnError(E_NOTIMPL); - } - - override int DTE( - /* [retval][out] */ dte.DTE *lppaReturn) - { - logCall("%s.get_DTE()", this); - dte._DTE _dte = queryService!(dte._DTE); - if(!_dte) - return returnError(E_NOINTERFACE); - scope(exit) _dte.Release(); - return _dte.DTE(lppaReturn); - } - - override int Kind( - /* [retval][out] */ BSTR *lpbstrName) - { - logCall("get_Kind(lpbstrName=%s)", _toLog(lpbstrName)); - wstring s = GUID2wstring(g_projectFactoryCLSID); - *lpbstrName = allocwBSTR(s); - return S_OK; - } - - override int ProjectItems( - /* [retval][out] */ dte.ProjectItems* lppcReturn) - { - mixin(LogCallMix); - *lppcReturn = addref(mProjectItems); - return S_OK; - } - - override int Properties( - /* [retval][out] */ dte.Properties *ppObject) - { - mixin(LogCallMix); - *ppObject = addref(mProperties); - return S_OK; - } - - override int UniqueName( - /* [retval][out] */ BSTR *lpbstrName) - { - logCall("get_UniqueName(lpbstrName=%s)", _toLog(lpbstrName)); - - if (!mProject) - return returnError(E_FAIL); - - IVsSolution srpSolution = queryService!(IVsSolution); - if(!srpSolution) - return returnError(E_FAIL); - - IVsHierarchy pIVsHierarchy = mProject; // ->GetIVsHierarchy(); - - int hr = srpSolution.GetUniqueNameOfProject(pIVsHierarchy, lpbstrName); - srpSolution.Release(); - - return hr; - } - - override int Object( - /* [retval][out] */ IDispatch* ProjectModel) - { - logCall("%s.get_Object(out ProjectModel=%s)", this, _toLog(&ProjectModel)); - *ProjectModel = addref(mProject); - return S_OK; - } - - override int Extender( - /* [in] */ in BSTR ExtenderName, - /* [retval][out] */ IDispatch *Extender) - { - logCall("%s.get_Extender(ExtenderName=%s)", this, _toLog(ExtenderName)); - return returnError(E_NOTIMPL); - } - - override int ExtenderNames( - /* [retval][out] */ VARIANT *ExtenderNames) - { - logCall("%s.get_ExtenderNames(ExtenderNames=%s)", this, _toLog(ExtenderNames)); - return returnError(E_NOTIMPL); - } - - override int ExtenderCATID( - /* [retval][out] */ BSTR *pRetval) - { - logCall("get_ExtenderCATID(pRetval=%s)", _toLog(pRetval)); - return returnError(E_NOTIMPL); - } - - override int FullName( - /* [retval][out] */ BSTR *lpbstrName) - { - logCall("get_FullName(lpbstrName=%s)", _toLog(lpbstrName)); - return FileName(lpbstrName); - } - - override int Saved( - /* [retval][out] */ VARIANT_BOOL *lpfReturn) - { - mixin(LogCallMix); - return returnError(E_NOTIMPL); - } - - override int Saved( - /* [in] */ in VARIANT_BOOL SavedFlag) - { - logCall("put_Saved(SavedFlag=%s)", _toLog(SavedFlag)); - return returnError(E_NOTIMPL); - } - - override int ConfigurationManager( - /* [retval][out] */ dte.ConfigurationManager* ppConfigurationManager) - { - mixin(LogCallMix); - - *ppConfigurationManager = mProject.getConfigurationManager(); - return S_OK; - } - - override int Globals( - /* [retval][out] */ dte.Globals* ppGlobals) - { - mixin(LogCallMix); - - HRESULT hr = S_OK; - // hr = CheckEnabledItem(this, &IID__DTE, L"Globals"); - // IfFailRet(hr); - - // if don't already have m_srpGlobals, get it from shell - IVsExtensibility3 ext = queryService!(dte.IVsExtensibility, IVsExtensibility3); - if(!ext) - return E_FAIL; - scope(exit) release(ext); - - dte.Globals globals; - VARIANT varIVsGlobalsCallback; - varIVsGlobalsCallback.vt = VT_UNKNOWN; - IVsHierarchy pIVsHierarchy = mProject; - hr = mProject.QueryInterface(&IID_IUnknown, cast(void**)&varIVsGlobalsCallback.punkVal); - if(!FAILED(hr)) - { - //! TODO fix: returns failure - hr = ext.GetGlobalsObject(varIVsGlobalsCallback, cast(IUnknown*) &globals); - varIVsGlobalsCallback.punkVal.Release(); - } - - *ppGlobals = globals; - return hr; - } - - override int Save( - /* [defaultvalue] */ BSTR FileName) - { - logCall("Save(FileName=%s)", _toLog(FileName)); - return returnError(E_NOTIMPL); - } - - override int ParentProjectItem( - /* [retval][out] */ dte.ProjectItem *ppParentProjectItem) - { - mixin(LogCallMix); - return returnError(E_NOTIMPL); - } - - override int CodeModel( - /* [retval][out] */ dte.CodeModel *ppCodeModel) - { - mixin(LogCallMix); - return returnError(E_NOTIMPL); - } - - override int Delete() - { - mixin(LogCallMix); - return returnError(E_NOTIMPL); - } - - - ////////////////////////////////////////////////////////////// - __gshared ComTypeInfoHolder mTypeHolder; - static void shared_static_this_typeHolder() - { - static class _ComTypeInfoHolder : ComTypeInfoHolder - { - override int GetIDsOfNames( - /* [size_is][in] */ in LPOLESTR *rgszNames, - /* [in] */ in UINT cNames, - /* [size_is][out] */ MEMBERID *pMemId) - { - //mixin(LogCallMix); - if (cNames == 1 && to_string(*rgszNames) == "Name") - { - *pMemId = 1; - return S_OK; - } - return returnError(E_NOTIMPL); - } - } - mTypeHolder = newCom!_ComTypeInfoHolder; - addref(mTypeHolder); - } - static void shared_static_dtor_typeHolder() - { - mTypeHolder = release(mTypeHolder); - } - - override ComTypeInfoHolder getTypeHolder () { return mTypeHolder; } - - Project mProject; - dte.ProjectItems mProjectItems; - dte.Properties mProperties; -} - /////////////////////////////////////////////////////////////////////// class Project : CVsHierarchy, @@ -931,7 +220,6 @@ class Project : CVsHierarchy, mFactory = factory; mCaption = mName = name; mFilename = filename; - mExtProject = addref(newCom!ExtProject(this)); mConfigProvider = addref(newCom!ConfigProvider(this)); parseXML(); @@ -941,7 +229,6 @@ class Project : CVsHierarchy, mFactory = factory; mCaption = mName = name; mFilename = filename; - mExtProject = addref(newCom!ExtProject(this)); mConfigProvider = addref(newCom!ConfigProvider(this)); mConfigProvider.addConfig(platform, config); @@ -1402,6 +689,23 @@ class Project : CVsHierarchy, { //mixin(LogCallMix); + if(itemid == VSITEMID_ROOT) + { + // handle project specific stuff before generic node properties + switch(propid) + { + case VSHPROPID_ExtObject: + var.vt = VT_DISPATCH; + if(!mExtProject) + mExtProject = addref(newCom!ExtProject(this)); + var.pdispVal = addref(mExtProject); + return S_OK; + + default: + break; + } + } + if(super.GetProperty(itemid, propid, var) == S_OK) return S_OK; if(itemid != VSITEMID_ROOT) @@ -1433,12 +737,6 @@ class Project : CVsHierarchy, var.vt = VT_DISPATCH; return QueryInterface(&IDispatch.iid, cast(void **)&var.pdispVal); - case VSHPROPID_ExtObject: - var.vt = VT_DISPATCH; - var.pdispVal = addref(mExtProject); - break; - //return DISP_E_MEMBERNOTFOUND; - case VSHPROPID_ConfigurationProvider: var.vt = VT_UNKNOWN; return GetCfgProvider(cast(IVsCfgProvider*)&var.punkVal); @@ -2096,7 +1394,23 @@ class Project : CVsHierarchy, /+[out]+/ CADWORD *pCaFlagsOut) // Flags per file { mixin(LogCallMix); - return E_NOTIMPL; + + CHierNode node = VSITEMID2Node(itemid); + if(node) + { + pCaStringsOut.pElems = cast(wchar**) CoTaskMemAlloc(pCaStringsOut.pElems[0].sizeof); + pCaStringsOut.cElems = 1; + pCaStringsOut.pElems[0] = string2OLESTR(node.GetFullPath()); + + pCaFlagsOut.pElems = cast(uint*) CoTaskMemAlloc(pCaFlagsOut.pElems[0].sizeof); + pCaFlagsOut.cElems = 1; + pCaFlagsOut.pElems[0] = SFF_NoFlags; + + logCall(" %s.GetSccFiles returns %s", this, _toLog(pCaStringsOut.pElems[0])); + return S_OK; + } + + return S_FALSE; } override HRESULT GetSccSpecialFiles(in VSITEMID itemid, // node in project hierarchy @@ -3174,6 +2488,8 @@ Error: } string GetFilename() { return mFilename; } + string GetCaption() { return mCaption; } + void SetCaption(string caption) { mCaption = caption; } private: ProjectFactory mFactory; diff --git a/visuald/hierarchy.d b/visuald/hierarchy.d index a6dbf383..82eccdc2 100644 --- a/visuald/hierarchy.d +++ b/visuald/hierarchy.d @@ -105,7 +105,8 @@ class CFileNode : CHierNode, scope(exit) release(sccmgr); auto path = _toUTF16z(GetFullPath()); VsStateIcon icon; - if(sccmgr.GetSccGlyph(1, &path, &icon, null) == S_OK) + DWORD sccStatus; + if(sccmgr.GetSccGlyph(1, &path, &icon, &sccStatus) == S_OK) var.lVal = icon; } return S_OK; diff --git a/visuald/logutil.d b/visuald/logutil.d index 7b325acc..deceed50 100644 --- a/visuald/logutil.d +++ b/visuald/logutil.d @@ -89,6 +89,8 @@ string GUID2utf8(ref const(GUID) guid) mixin(mixinGUID2string("IUnknown")); mixin(mixinGUID2string("IClassFactory")); mixin(mixinGUID2string("IMarshal")); + mixin(mixinGUID2string("INoMarshal")); + mixin(mixinGUID2string("IAgileObject")); mixin(mixinGUID2string("IMallocSpy")); mixin(mixinGUID2string("IStdMarshalInfo")); mixin(mixinGUID2string("IExternalConnection")); @@ -316,6 +318,7 @@ version(none) mixin(mixinGUID2string("IPropertyBag")); mixin(mixinGUID2string("IErrorLog")); mixin(mixinGUID2string("IProvideMultipleClassInfo")); + mixin(mixinGUID2string("ISupportErrorInfo")); mixin(mixinGUID2string("IUseImmediateCommitPropertyPages")); mixin(mixinGUID2string("SolutionProperties")); diff --git a/visuald/oledatasource.d b/visuald/oledatasource.d index ec148834..5e3cfe12 100644 --- a/visuald/oledatasource.d +++ b/visuald/oledatasource.d @@ -529,6 +529,13 @@ class CEnumFormatEtc : DComObject, IEnumFORMATETC mPos = 0; } + override HRESULT QueryInterface(in IID* riid, void** pvObject) + { + if(queryInterface!(IEnumFORMATETC) (this, riid, pvObject)) + return S_OK; + return super.QueryInterface(riid, pvObject); + } + bool findValid() { while(mPos < mSrc.mCache.length) diff --git a/visuald/propertypage.d b/visuald/propertypage.d index 69614e6a..3b7320e3 100644 --- a/visuald/propertypage.d +++ b/visuald/propertypage.d @@ -1168,6 +1168,12 @@ class DmdLinkerPropertyPage : ProjectPropertyPage override string GetCategoryName() { return "Linker"; } override string GetPageName() { return "General"; } + override void UpdateDirty(bool bDirty) + { + super.UpdateDirty(bDirty); + EnableControls(); + } + override void CreateControls() { AddControl("Output File", mExeFile = new Text(mCanvas)); @@ -1181,8 +1187,15 @@ class DmdLinkerPropertyPage : ProjectPropertyPage [ "Minimum", "Symbols By Address", "Standard", "Full", "With cross references" ], false)); AddControl("", mImplib = new CheckBox(mCanvas, "Create import library")); AddControl("", mUseStdLibPath = new CheckBox(mCanvas, "Use global and standard library search paths")); + AddControl("C Runtime", mCRuntime = new ComboBox(mCanvas, [ "None", "Static Release (LIBCMT)", "Static Debug (LIBCMTD)", "Dynamic Release (MSCVRT)", "Dynamic Release (MSCVRTD)" ], false)); } + void EnableControls() + { + if(ProjectOptions options = GetProjectOptions()) + mCRuntime.setEnabled(options.isX86_64); + } + override void SetControls(ProjectOptions options) { mExeFile.setText(options.exefile); @@ -1194,6 +1207,9 @@ class DmdLinkerPropertyPage : ProjectPropertyPage mGenMap.setSelection(options.mapverbosity); mImplib.setChecked(options.createImplib); mUseStdLibPath.setChecked(options.useStdLibPath); + mCRuntime.setSelection(options.cRuntime); + + EnableControls(); } override int DoApply(ProjectOptions options, ProjectOptions refoptions) @@ -1208,6 +1224,7 @@ class DmdLinkerPropertyPage : ProjectPropertyPage changes += changeOption(cast(uint) mGenMap.getSelection(), options.mapverbosity, refoptions.mapverbosity); changes += changeOption(mImplib.isChecked(), options.createImplib, refoptions.createImplib); changes += changeOption(mUseStdLibPath.isChecked(), options.useStdLibPath, refoptions.useStdLibPath); + changes += changeOption(cast(uint) mCRuntime.getSelection(), options.cRuntime, refoptions.cRuntime); return changes; } @@ -1220,6 +1237,7 @@ class DmdLinkerPropertyPage : ProjectPropertyPage ComboBox mGenMap; CheckBox mImplib; CheckBox mUseStdLibPath; + ComboBox mCRuntime; } class DmdEventsPropertyPage : ProjectPropertyPage @@ -1491,7 +1509,7 @@ class DirPropertyPage : GlobalPropertyPage AddControl("Executable paths", mExePath64 = new MultiLineText(page64)); mLinesPerMultiLine = 2; AddControl("Library paths", mLibPath64 = new MultiLineText(page64)); - + if(overrideIni.length) { AddControl("", mOverrideIni64 = new CheckBox(page64, overrideIni)); diff --git a/visuald/visuald.visualdproj b/visuald/visuald.visualdproj index d56cd632..ecea3b57 100644 --- a/visuald/visuald.visualdproj +++ b/visuald/visuald.visualdproj @@ -492,6 +492,7 @@ + @@ -605,6 +606,7 @@ rc /fo"$(OutDir)\visuald.res" $(InputPath)" outfile="$(OutDir)\visuald +