diff --git a/Uninstall/src/!ToDo/MSDN Library for Visual Studio 2008 - ENU.reg b/Uninstall/src/!ToDo/MSDN Library for Visual Studio 2008 - ENU.reg new file mode 100644 index 0000000..201a48f Binary files /dev/null and b/Uninstall/src/!ToDo/MSDN Library for Visual Studio 2008 - ENU.reg differ diff --git a/Uninstall/src/!ToDo/Microsoft Visual Studio 2008 Remote Debugger - ENU.reg b/Uninstall/src/!ToDo/Microsoft Visual Studio 2008 Remote Debugger - ENU.reg new file mode 100644 index 0000000..174be82 Binary files /dev/null and b/Uninstall/src/!ToDo/Microsoft Visual Studio 2008 Remote Debugger - ENU.reg differ diff --git a/Uninstall/src/!ToDo/Microsoft Visual Studio Team System 2008 Team Suite - ENU.reg b/Uninstall/src/!ToDo/Microsoft Visual Studio Team System 2008 Team Suite - ENU.reg new file mode 100644 index 0000000..f355182 Binary files /dev/null and b/Uninstall/src/!ToDo/Microsoft Visual Studio Team System 2008 Team Suite - ENU.reg differ diff --git a/Uninstall/src/.gitignore b/Uninstall/src/.gitignore new file mode 100644 index 0000000..fe3c659 --- /dev/null +++ b/Uninstall/src/.gitignore @@ -0,0 +1,2 @@ +*.exe +\!ToDo.txt diff --git a/Uninstall/src/Descript.ion b/Uninstall/src/Descript.ion new file mode 100644 index 0000000..c36feb2 --- /dev/null +++ b/Uninstall/src/Descript.ion @@ -0,0 +1 @@ +project.ini version diff --git a/Uninstall/src/DlgBuilder.hpp b/Uninstall/src/DlgBuilder.hpp index f92e77f..d519acf 100644 --- a/Uninstall/src/DlgBuilder.hpp +++ b/Uninstall/src/DlgBuilder.hpp @@ -76,13 +76,13 @@ struct CheckBoxBinding: public DialogItemBinding virtual void SaveValue(T *Item, int RadioGroupIndex) { - if (Mask == 0) + if(Mask == 0) { *Value = Item->Selected; } else { - if (Item->Selected) + if(Item->Selected) *Value |= Mask; else *Value &= ~Mask; @@ -101,7 +101,7 @@ struct RadioButtonBinding: public DialogItemBinding virtual void SaveValue(T *Item, int RadioGroupIndex) { - if (Item->Selected) + if(Item->Selected) *Value = RadioGroupIndex; } }; @@ -177,7 +177,8 @@ class DialogBuilderBase // чтобы все нормальные диалоги помещались без реаллокации // TODO хорошо бы, чтобы они вообще не инвалидировались DialogItemsAllocated += 128; - if (DialogItems == nullptr) + + if(DialogItems == nullptr) { DialogItems = new T[DialogItemsAllocated]; Bindings = new DialogItemBinding * [DialogItemsAllocated]; @@ -186,11 +187,13 @@ class DialogBuilderBase { T *NewDialogItems = new T[DialogItemsAllocated]; DialogItemBinding **NewBindings = new DialogItemBinding * [DialogItemsAllocated]; + for(int i=0; iX1 = 5; @@ -234,24 +238,23 @@ class DialogBuilderBase { switch(Item.Type) { - case DI_TEXT: - return TextWidth(Item); - - case DI_CHECKBOX: - case DI_RADIOBUTTON: - return TextWidth(Item) + 4; - - case DI_EDIT: - case DI_FIXEDIT: - case DI_COMBOBOX: - int Width = Item.X2 - Item.X1 + 1; - /* стрелка history занимает дополнительное место, но раньше она рисовалась поверх рамки - if (Item.Flags & DIF_HISTORY) - Width++; - */ - return Width; - break; + case DI_TEXT: + return TextWidth(Item); + case DI_CHECKBOX: + case DI_RADIOBUTTON: + return TextWidth(Item) + 4; + case DI_EDIT: + case DI_FIXEDIT: + case DI_COMBOBOX: + int Width = Item.X2 - Item.X1 + 1; + /* стрелка history занимает дополнительное место, но раньше она рисовалась поверх рамки + if (Item.Flags & DIF_HISTORY) + Width++; + */ + return Width; + break; } + return 0; } @@ -272,33 +275,41 @@ class DialogBuilderBase int MaxTextWidth() { int MaxWidth = 0; + for(int i=1; i *Binding = FindBinding(DialogItems+i); int BeforeWidth = 0; - if (Binding && Binding->BeforeLabelID != -1) { + + if(Binding && Binding->BeforeLabelID != -1) + { BeforeWidth = DialogItems [Binding->BeforeLabelID].X2 - DialogItems [Binding->BeforeLabelID].X1 + 1; } @@ -306,11 +317,12 @@ class DialogBuilderBase DialogItems [i].X1 = SecondColumnX1 + BeforeWidth; DialogItems [i].X2 = DialogItems [i].X1 + Width; - if (Binding && Binding->AfterLabelID != -1) + if(Binding && Binding->AfterLabelID != -1) { int j = Binding->AfterLabelID; int AfterWidth = DialogItems [j].X2 - DialogItems [j].X1; - if (DialogItems [j].X1 == SECOND_COLUMN) + + if(DialogItems [j].X1 == SECOND_COLUMN) { DialogItems [j].X1 = SecondColumnX1 + Width + 2; DialogItems [j].X2 = DialogItems [j].X1 + AfterWidth; @@ -328,15 +340,16 @@ class DialogBuilderBase void UpdateRightSlidePosition() { int SlideX2 = DialogItems [0].X2 - 2; + for(int i=0; i(Item - DialogItems); - if (Index >= 0 && Index < DialogItemsCount) + + if(Index >= 0 && Index < DialogItemsCount) return Index; + return -1; } DialogItemBinding* FindBinding(const T *Item) { int Index = static_cast(Item - DialogItems); - if (Index >= 0 && Index < DialogItemsCount) + + if(Index >= 0 && Index < DialogItemsCount) return Bindings [Index]; + return nullptr; } void SaveValues() { int RadioGroupIndex = 0; + for(int i=0; iSaveValue(&DialogItems [i], RadioGroupIndex); } } @@ -423,9 +441,10 @@ class DialogBuilderBase { for(int i=0; iX2 = Item->X1 + ItemWidth(*Item); - if (Mask == 0) + + if(Mask == 0) Item->Selected = *Value; else Item->Selected = (*Value & Mask) != 0; + SetLastItemBinding(CreateCheckBoxBinding(Value, Mask)); return Item; } @@ -467,30 +488,39 @@ class DialogBuilderBase // Добавляет группу радиокнопок. int AddRadioButtons(int *Value, int OptionCount, int MessageIDs[], DWORD AddFlags=0, BOOL abTwoColumns = FALSE) { - if (abTwoColumns && (ColumnStartIndex != -1 || OptionCount < 2)) + if(abTwoColumns && (ColumnStartIndex != -1 || OptionCount < 2)) abTwoColumns = FALSE; - if (abTwoColumns) + + if(abTwoColumns) StartColumns(); int nBreakColumn = abTwoColumns ? (((OptionCount+1)>>1)-1) : (OptionCount+1); int nFirstID = DialogItemsCount; + for(int i=0; iX2 = Item->X1 + ItemWidth(*Item); - if (i == 0) + + if(i == 0) Item->Flags |= DIF_GROUP; - if (*Value == i) + + if(*Value == i) Item->Selected = TRUE; - if (AddFlags) + + if(AddFlags) Item->Flags |= AddFlags; + SetLastItemBinding(CreateRadioButtonBinding(Value)); - if (i == nBreakColumn) + + if(i == nBreakColumn) ColumnBreak(); } - if (abTwoColumns) + + if(abTwoColumns) EndColumns(); + return nFirstID; } @@ -498,13 +528,15 @@ class DialogBuilderBase T* AddComboBox(int Width, FarList* ListItems, int *Value, DWORD AddFlags=DIF_DROPDOWNLIST) { T *Item = AddDialogItem(DI_COMBOBOX, nullptr); - for (int i = 0; i < ListItems->ItemsNumber; i++) + + for(int i = 0; i < ListItems->ItemsNumber; i++) { - if (i == *Value) + if(i == *Value) ListItems->Items[i].Flags |= LIF_SELECTED; - else if (ListItems->Items[i].Flags & LIF_SELECTED) + else if(ListItems->Items[i].Flags & LIF_SELECTED) ListItems->Items[i].Flags &= ~LIF_SELECTED; } + Item->ListItems = ListItems; Item->Flags |= AddFlags; SetNextY(Item); @@ -526,40 +558,36 @@ class DialogBuilderBase Item->Y1 = Item->Y2 = RelativeTo->Y1; Item->X1 = 5; Item->X2 = Item->X1 + ItemWidth(*Item) - 1; - int RelativeToWidth = RelativeTo->X2 - RelativeTo->X1; RelativeTo->X1 = Item->X2 + 2; RelativeTo->X2 = RelativeTo->X1 + RelativeToWidth; - //// Текст должен идти первым элементом, чтобы хоткеи срабатывали //T P; P = *RelativeTo; *RelativeTo = *Item; *Item = P; //Item--; RelativeTo++; - //int I1 = static_cast(Item - DialogItems); //int I2 = static_cast(RelativeTo - DialogItems); //DialogItemBinding *B1; //B1 = Bindings[I1]; Bindings[I1] = Bindings[I2]; Bindings[I2] = B1; - DialogItemBinding *Binding = FindBinding(RelativeTo); - if (Binding) + + if(Binding) Binding->BeforeLabelID = GetItemID(Item); return Item; } - + // Подвязать (a'la AddTextAfter) любой элемент к любому элементу void MoveItemAfter(T *FirstItem, T *AfterItem) { int Width = ItemWidth(*AfterItem); int Height = AfterItem->Y2 - AfterItem->Y1; - AfterItem->Y1 = FirstItem->Y1; AfterItem->Y2 = FirstItem->Y1 + Height; AfterItem->X1 = FirstItem->X1 + ItemWidth(*FirstItem); AfterItem->X2 = AfterItem->X1 + Width - 1; - DialogItemBinding *Binding = FindBinding(AfterItem); - if (Binding) + + if(Binding) { Binding->BeforeLabelID = GetItemID(FirstItem); _ASSERTE(Binding->BeforeLabelID != -1); @@ -574,9 +602,9 @@ class DialogBuilderBase T *Item = AddDialogItem(DI_TEXT, GetLangString(LabelId)); Item->Y1 = Item->Y2 = RelativeTo->Y1; Item->X1 = RelativeTo->X2 + 2; - DialogItemBinding *Binding = FindBinding(RelativeTo); - if (Binding) + + if(Binding) Binding->AfterLabelID = GetItemID(Item); return Item; @@ -603,26 +631,28 @@ class DialogBuilderBase for(int i=ColumnStartIndex; i *Binding = FindBinding(DialogItems + i); int BindingAdd = 0; - if (Binding) { - if (Binding->BeforeLabelID != -1) + + if(Binding) + { + if(Binding->BeforeLabelID != -1) BindingAdd = ItemWidth(DialogItems [Binding->BeforeLabelID]) + 1; - else if (Binding->AfterLabelID != -1) + else if(Binding->AfterLabelID != -1) BindingAdd = ItemWidth(DialogItems [Binding->AfterLabelID]) + 1; } - if ((Width + BindingAdd) > ColumnMinWidth) + if((Width + BindingAdd) > ColumnMinWidth) ColumnMinWidth = Width + BindingAdd; - if (i >= ColumnBreakIndex) + + if(i >= ColumnBreakIndex) { DialogItems [i].X1 = SECOND_COLUMN; DialogItems [i].X2 = SECOND_COLUMN + Width; } } - if (ColumnEndY > NextY) + if(ColumnEndY > NextY) NextY = ColumnEndY; ColumnStartIndex = -1; @@ -648,13 +678,11 @@ class DialogBuilderBase void AddOKCancel(int OKMessageId, int CancelMessageId) { AddSeparator(); - T *OKButton = AddDialogItem(DI_BUTTON, GetLangString(OKMessageId)); OKButton->Flags = DIF_CENTERGROUP; OKButton->DefaultButton = TRUE; OKButton->Y1 = OKButton->Y2 = NextY++; OKButtonID = DialogItemsCount-1; - T *CancelButton = AddDialogItem(DI_BUTTON, GetLangString(CancelMessageId)); CancelButton->Flags = DIF_CENTERGROUP; CancelButton->Y1 = CancelButton->Y2 = OKButton->Y1; @@ -665,17 +693,18 @@ class DialogBuilderBase { AddSeparator(); - for (int i = 0; i < nBtnCount; i++) + for(int i = 0; i < nBtnCount; i++) { T *Button = AddDialogItem(DI_BUTTON, GetLangString(BtnID[i])); Button->Flags = DIF_CENTERGROUP; Button->DefaultButton = TRUE; Button->Y1 = Button->Y2 = NextY; - if (i == 0) + + if(i == 0) OKButtonID = DialogItemsCount-1; } - CancelButtonID = DialogItemsCount-1; + CancelButtonID = DialogItemsCount-1; NextY++; } @@ -686,12 +715,16 @@ class DialogBuilderBase UpdateSecondColumnPosition(); UpdateRightSlidePosition(); int Result = DoShowDialog(); - if (Result >= OKButtonID && Result < CancelButtonID) + + if(Result >= OKButtonID && Result < CancelButtonID) { SaveValues(); - if (pnBtnNo) *pnBtnNo = (Result - OKButtonID); + + if(pnBtnNo) *pnBtnNo = (Result - OKButtonID); + return true; } + return false; } }; @@ -700,44 +733,45 @@ class PluginDialogBuilder; class DialogAPIBinding: public DialogItemBinding { -protected: - const PluginStartupInfo &Info; - HANDLE *DialogHandle; - int ID; + protected: + const PluginStartupInfo &Info; + HANDLE *DialogHandle; + int ID; - DialogAPIBinding(const PluginStartupInfo &aInfo, HANDLE *aHandle, int aID) - : Info(aInfo), DialogHandle(aHandle), ID(aID) - { - } + DialogAPIBinding(const PluginStartupInfo &aInfo, HANDLE *aHandle, int aID) + : Info(aInfo), DialogHandle(aHandle), ID(aID) + { + } }; class PluginCheckBoxBinding: public DialogAPIBinding { - BOOL *Value; - int Mask; - -public: - PluginCheckBoxBinding(const PluginStartupInfo &aInfo, HANDLE *aHandle, int aID, BOOL *aValue, int aMask) - : DialogAPIBinding(aInfo, aHandle, aID), - Value(aValue), Mask(aMask) - { - } + BOOL *Value; + int Mask; - virtual void SaveValue(FarDialogItem *Item, int RadioGroupIndex) - { - BOOL Selected = static_cast(Info.SendDlgMessage(*DialogHandle, DM_GETCHECK, ID, 0)); - if (Mask == 0) + public: + PluginCheckBoxBinding(const PluginStartupInfo &aInfo, HANDLE *aHandle, int aID, BOOL *aValue, int aMask) + : DialogAPIBinding(aInfo, aHandle, aID), + Value(aValue), Mask(aMask) { - *Value = Selected; } - else + + virtual void SaveValue(FarDialogItem *Item, int RadioGroupIndex) { - if (Selected) - *Value |= Mask; + BOOL Selected = static_cast(Info.SendDlgMessage(*DialogHandle, DM_GETCHECK, ID, 0)); + + if(Mask == 0) + { + *Value = Selected; + } else - *Value &= ~Mask; + { + if(Selected) + *Value |= Mask; + else + *Value &= ~Mask; + } } - } }; class PluginRadioButtonBinding: public DialogAPIBinding @@ -754,7 +788,7 @@ class PluginRadioButtonBinding: public DialogAPIBinding virtual void SaveValue(FarDialogItem *Item, int RadioGroupIndex) { - if (Info.SendDlgMessage(*DialogHandle, DM_GETCHECK, ID, 0)) + if(Info.SendDlgMessage(*DialogHandle, DM_GETCHECK, ID, 0)) *Value = RadioGroupIndex; } }; @@ -781,105 +815,109 @@ class PluginComboBoxBinding: public DialogAPIBinding class PluginEditFieldBinding: public DialogAPIBinding { -private: - TCHAR *Value; - int MaxSize; + private: + TCHAR *Value; + int MaxSize; -public: - PluginEditFieldBinding(const PluginStartupInfo &aInfo, HANDLE *aHandle, int aID, TCHAR *aValue, int aMaxSize) - : DialogAPIBinding(aInfo, aHandle, aID), Value(aValue), MaxSize(aMaxSize) - { - } + public: + PluginEditFieldBinding(const PluginStartupInfo &aInfo, HANDLE *aHandle, int aID, TCHAR *aValue, int aMaxSize) + : DialogAPIBinding(aInfo, aHandle, aID), Value(aValue), MaxSize(aMaxSize) + { + } - virtual void SaveValue(FarDialogItem *Item, int RadioGroupIndex) - { - const TCHAR *DataPtr = (const TCHAR *) Info.SendDlgMessage(*DialogHandle, DM_GETCONSTTEXTPTR, ID, 0); - lstrcpyn(Value, DataPtr, MaxSize); - } + virtual void SaveValue(FarDialogItem *Item, int RadioGroupIndex) + { + const TCHAR *DataPtr = (const TCHAR *) Info.SendDlgMessage(*DialogHandle, DM_GETCONSTTEXTPTR, ID, 0); + lstrcpyn(Value, DataPtr, MaxSize); + } }; class PluginIntEditFieldBinding: public DialogAPIBinding { -private: - int *Value; - TCHAR Buffer[32]; - TCHAR Mask[32]; + private: + int *Value; + TCHAR Buffer[32]; + TCHAR Mask[32]; -public: - PluginIntEditFieldBinding(const PluginStartupInfo &aInfo, HANDLE *aHandle, int aID, int *aValue, int Width) - : DialogAPIBinding(aInfo, aHandle, aID), - Value(aValue) - { - aInfo.FSF->itoa(*aValue, Buffer, 10); - int MaskWidth = Width < 31 ? Width : 31; - for(int i=0; iitoa(*aValue, Buffer, 10); + int MaskWidth = Width < 31 ? Width : 31; - virtual void SaveValue(FarDialogItem *Item, int RadioGroupIndex) - { - const TCHAR *DataPtr = (const TCHAR *) Info.SendDlgMessage(*DialogHandle, DM_GETCONSTTEXTPTR, ID, 0); - *Value = Info.FSF->atoi(DataPtr); - } + for(int i=0; iatoi(DataPtr); + } + + TCHAR* GetBuffer() + { + return Buffer; + } + + const TCHAR* GetMask() + { + return Mask; + } }; #else class PluginEditFieldBinding: public DialogItemBinding { -private: - TCHAR *Value; - int MaxSize; + private: + TCHAR *Value; + int MaxSize; -public: - PluginEditFieldBinding(TCHAR *aValue, int aMaxSize) - : Value(aValue), MaxSize(aMaxSize) - { - } + public: + PluginEditFieldBinding(TCHAR *aValue, int aMaxSize) + : Value(aValue), MaxSize(aMaxSize) + { + } - virtual void SaveValue(FarDialogItem *Item, int RadioGroupIndex) - { - lstrcpyn(Value, Item->Data, MaxSize); - } + virtual void SaveValue(FarDialogItem *Item, int RadioGroupIndex) + { + lstrcpyn(Value, Item->Data, MaxSize); + } }; class PluginIntEditFieldBinding: public DialogItemBinding { -private: - const PluginStartupInfo &Info; - int *Value; - TCHAR Mask[32]; + private: + const PluginStartupInfo &Info; + int *Value; + TCHAR Mask[32]; -public: - PluginIntEditFieldBinding(const PluginStartupInfo &aInfo, int *aValue, int Width) - : Info(aInfo), Value(aValue) - { - int MaskWidth = Width < 31 ? Width : 31; - for(int i=0; iatoi(Item->Data); - } + for(int i=0; iatoi(Item->Data); + } + + const TCHAR* GetMask() + { + return Mask; + } }; #endif @@ -899,13 +937,14 @@ class PluginDialogBuilder: public DialogBuilderBase virtual void InitDialogItem(FarDialogItem *Item, const TCHAR *Text) { memset(Item, 0, sizeof(FarDialogItem)); - if (Text) + + if(Text) { - #ifdef UNICODE - Item->PtrData = Text; - #else - lstrcpyn(Item->Data, Text, sizeof(Item->Data)/sizeof(Item->Data[0])); - #endif +#ifdef UNICODE + Item->PtrData = Text; +#else + lstrcpyn(Item->Data, Text, sizeof(Item->Data)/sizeof(Item->Data[0])); +#endif } } @@ -929,11 +968,11 @@ class PluginDialogBuilder: public DialogBuilderBase int Height = DialogItems [0].Y2+2; #ifdef UNICODE DialogHandle = Info.DialogInit(Info.ModuleNumber, -1, -1, Width, Height, - HelpTopic, DialogItems, DialogItemsCount, 0, DialogFlags, nullptr, 0); + HelpTopic, DialogItems, DialogItemsCount, 0, DialogFlags, nullptr, 0); return Info.DialogRun(DialogHandle); #else return Info.DialogEx(Info.ModuleNumber, -1, -1, Width, Height, - HelpTopic, DialogItems, DialogItemsCount, 0, DialogFlags, nullptr, 0); + HelpTopic, DialogItems, DialogItemsCount, 0, DialogFlags, nullptr, 0); #endif } @@ -964,7 +1003,7 @@ class PluginDialogBuilder: public DialogBuilderBase #endif } -public: + public: PluginDialogBuilder(const PluginStartupInfo &aInfo, int TitleMessageID, const TCHAR *aHelpTopic) : DialogFlags(0), Info(aInfo), DialogHandle(NULL), HelpTopic(aHelpTopic) { @@ -974,18 +1013,21 @@ class PluginDialogBuilder: public DialogBuilderBase ~PluginDialogBuilder() { #ifdef UNICODE - if (DialogHandle) + + if(DialogHandle) { Info.DialogFree(DialogHandle); DialogHandle = NULL; } + #endif } FarDialogItem* GetItemByIndex(int Index) { - if (Index >= 0 && Index < DialogItemsCount) + if(Index >= 0 && Index < DialogItemsCount) return (DialogItems + Index); + return NULL; } @@ -1006,8 +1048,6 @@ class PluginDialogBuilder: public DialogBuilderBase Binding = new PluginIntEditFieldBinding(Info, Value, Width); Info.FSF->itoa(*Value, (TCHAR *) Item->Data, 10); #endif - - #ifdef _FAR_NO_NAMELESS_UNIONS Item->Param.Mask = Binding->GetMask(); #else @@ -1024,7 +1064,8 @@ class PluginDialogBuilder: public DialogBuilderBase FarDialogItem *Item = AddDialogItem(DI_EDIT, Value); SetNextY(Item); Item->X2 = Item->X1 + Width; - if (HistoryID) + + if(HistoryID) { #ifdef _FAR_NO_NAMELESS_UNIONS Item->Param.History = HistoryID; diff --git a/Uninstall/src/DlgBuilder.hpp.orig b/Uninstall/src/DlgBuilder.hpp.orig new file mode 100644 index 0000000..f92e77f --- /dev/null +++ b/Uninstall/src/DlgBuilder.hpp.orig @@ -0,0 +1,1044 @@ +#pragma once + +/* +DlgBuilder.hpp + +Динамическое конструирование диалогов +*/ +/* +Copyright (c) 2009 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifdef UNICODE +#define EMPTY_TEXT L"" +#else +#define EMPTY_TEXT "" +#endif + +// Элемент выпадающего списка в диалоге. +struct DialogBuilderListItem +{ + // Строчка из LNG-файла, которая будет показана в диалоге. + int MessageId; + + // Значение, которое будет записано в поле Value при выборе этой строчки. + int ItemValue; +}; + +template +struct DialogItemBinding +{ + int BeforeLabelID; + int AfterLabelID; + + DialogItemBinding() + : BeforeLabelID(-1), AfterLabelID(-1) + { + } + + virtual void SaveValue(T *Item, int RadioGroupIndex) + { + } +}; + +template +struct CheckBoxBinding: public DialogItemBinding +{ + private: + BOOL *Value; + int Mask; + + public: + CheckBoxBinding(BOOL *aValue, int aMask) : Value(aValue), Mask(aMask) { } + + virtual void SaveValue(T *Item, int RadioGroupIndex) + { + if (Mask == 0) + { + *Value = Item->Selected; + } + else + { + if (Item->Selected) + *Value |= Mask; + else + *Value &= ~Mask; + } + } +}; + +template +struct RadioButtonBinding: public DialogItemBinding +{ + private: + int *Value; + + public: + RadioButtonBinding(int *aValue) : Value(aValue) { } + + virtual void SaveValue(T *Item, int RadioGroupIndex) + { + if (Item->Selected) + *Value = RadioGroupIndex; + } +}; + +template +struct ComboBoxBinding: public DialogItemBinding +{ + int *Value; + FarList *List; + + ComboBoxBinding(int *aValue, FarList *aList) + : Value(aValue), List(aList) + { + } + + ~ComboBoxBinding() + { + delete [] List->Items; + delete List; + } + + virtual void SaveValue(T *Item, int RadioGroupIndex) + { + FarListItem &ListItem = List->Items[Item->ListPos]; + *Value = ListItem.Reserved[0]; + } +}; + +/* +Класс для динамического построения диалогов. Автоматически вычисляет положение и размер +для добавляемых контролов, а также размер самого диалога. Автоматически записывает выбранные +значения в указанное место после закрытия диалога по OK. + +По умолчанию каждый контрол размещается в новой строке диалога. Ширина для текстовых строк, +checkbox и radio button вычисляется автоматически, для других элементов передаётся явно. +Есть также возможность добавить статический текст слева или справа от контрола, при помощи +методов AddTextBefore и AddTextAfter. + +Поддерживается также возможность расположения контролов в две колонки. Используется следующим +образом: +- StartColumns() +- добавляются контролы для первой колонки +- ColumnBreak() +- добавляются контролы для второй колонки +- EndColumns() + +Базовая версия класса используется как внутри кода FAR, так и в плагинах. +*/ + +template +class DialogBuilderBase +{ + protected: + T *DialogItems; + DialogItemBinding **Bindings; + int DialogItemsCount; + int DialogItemsAllocated; + int NextY; + int OKButtonID, CancelButtonID; + int ColumnStartIndex; + int ColumnBreakIndex; + int ColumnStartY; + int ColumnEndY; + int ColumnMinWidth; + + static const int SECOND_COLUMN = -2; + static const int RIGHT_SLIDE = -3; + + void ReallocDialogItems() + { + // реаллокация инвалидирует указатели на DialogItemEx, возвращённые из + // AddDialogItem и аналогичных методов, поэтому размер массива подбираем такой, + // чтобы все нормальные диалоги помещались без реаллокации + // TODO хорошо бы, чтобы они вообще не инвалидировались + DialogItemsAllocated += 128; + if (DialogItems == nullptr) + { + DialogItems = new T[DialogItemsAllocated]; + Bindings = new DialogItemBinding * [DialogItemsAllocated]; + } + else + { + T *NewDialogItems = new T[DialogItemsAllocated]; + DialogItemBinding **NewBindings = new DialogItemBinding * [DialogItemsAllocated]; + for(int i=0; iType = Type; + Bindings [Index] = nullptr; + return Item; + } + +public: + void SetNextY(T *Item) + { + Item->X1 = 5; + Item->Y1 = Item->Y2 = NextY++; + } + + void SlideItemUp(T *Item) + { + int Width = Item->X2 - Item->X1; + Item->X1 = RIGHT_SLIDE; + Item->X2 = Item->X1 + Width; + NextY--; + Item->Y1 = Item->Y2 = NextY - 1; + } + + int ItemWidth(const T &Item) + { + switch(Item.Type) + { + case DI_TEXT: + return TextWidth(Item); + + case DI_CHECKBOX: + case DI_RADIOBUTTON: + return TextWidth(Item) + 4; + + case DI_EDIT: + case DI_FIXEDIT: + case DI_COMBOBOX: + int Width = Item.X2 - Item.X1 + 1; + /* стрелка history занимает дополнительное место, но раньше она рисовалась поверх рамки + if (Item.Flags & DIF_HISTORY) + Width++; + */ + return Width; + break; + } + return 0; + } + + void AddBorder(const TCHAR *TitleText) + { + T *Title = AddDialogItem(DI_DOUBLEBOX, TitleText); + Title->X1 = 3; + Title->Y1 = 1; + } + + void UpdateBorderSize() + { + T *Title = &DialogItems[0]; + Title->X2 = Title->X1 + MaxTextWidth() + 3; + Title->Y2 = DialogItems [DialogItemsCount-1].Y2 + 1; + } + + int MaxTextWidth() + { + int MaxWidth = 0; + for(int i=1; i *Binding = FindBinding(DialogItems+i); + int BeforeWidth = 0; + if (Binding && Binding->BeforeLabelID != -1) { + BeforeWidth = DialogItems [Binding->BeforeLabelID].X2 - DialogItems [Binding->BeforeLabelID].X1 + 1; + } + + int Width = DialogItems [i].X2 - DialogItems [i].X1; + DialogItems [i].X1 = SecondColumnX1 + BeforeWidth; + DialogItems [i].X2 = DialogItems [i].X1 + Width; + + if (Binding && Binding->AfterLabelID != -1) + { + int j = Binding->AfterLabelID; + int AfterWidth = DialogItems [j].X2 - DialogItems [j].X1; + if (DialogItems [j].X1 == SECOND_COLUMN) + { + DialogItems [j].X1 = SecondColumnX1 + Width + 2; + DialogItems [j].X2 = DialogItems [j].X1 + AfterWidth; + } + else + { + DialogItems [j].X1 += Width + 2; + DialogItems [j].X2 += Width + 2; + } + } + } + } + } + + void UpdateRightSlidePosition() + { + int SlideX2 = DialogItems [0].X2 - 2; + for(int i=0; i *Binding) + { + Bindings [DialogItemsCount-1] = Binding; + } + + int GetItemID(T *Item) + { + int Index = static_cast(Item - DialogItems); + if (Index >= 0 && Index < DialogItemsCount) + return Index; + return -1; + } + + DialogItemBinding* FindBinding(const T *Item) + { + int Index = static_cast(Item - DialogItems); + if (Index >= 0 && Index < DialogItemsCount) + return Bindings [Index]; + return nullptr; + } + + void SaveValues() + { + int RadioGroupIndex = 0; + for(int i=0; iSaveValue(&DialogItems [i], RadioGroupIndex); + } + } + + virtual const TCHAR* GetLangString(int MessageID) + { + return nullptr; + } + + virtual int DoShowDialog() + { + return -1; + } + + virtual DialogItemBinding* CreateCheckBoxBinding(BOOL *Value, int Mask) + { + return nullptr; + } + + virtual DialogItemBinding* CreateComboBoxBinding(int *Value) + { + return nullptr; + } + + virtual DialogItemBinding* CreateRadioButtonBinding(int *Value) + { + return nullptr; + } + + DialogBuilderBase() + : DialogItems(nullptr), DialogItemsCount(0), DialogItemsAllocated(0), NextY(2), + ColumnStartIndex(-1), ColumnBreakIndex(-1), ColumnMinWidth(0) + { + } + + ~DialogBuilderBase() + { + for(int i=0; iFlags |= DIF_CENTERTEXT; + // Item->X2 = Item->X1 + ItemWidth(*Item); + //} + + // Добавляет чекбокс. + T* AddCheckbox(int TextMessageId, BOOL *Value, int Mask=0) + { + T *Item = AddDialogItem(DI_CHECKBOX, GetLangString(TextMessageId)); + SetNextY(Item); + Item->X2 = Item->X1 + ItemWidth(*Item); + if (Mask == 0) + Item->Selected = *Value; + else + Item->Selected = (*Value & Mask) != 0; + SetLastItemBinding(CreateCheckBoxBinding(Value, Mask)); + return Item; + } + + // Добавляет группу радиокнопок. + int AddRadioButtons(int *Value, int OptionCount, int MessageIDs[], DWORD AddFlags=0, BOOL abTwoColumns = FALSE) + { + if (abTwoColumns && (ColumnStartIndex != -1 || OptionCount < 2)) + abTwoColumns = FALSE; + if (abTwoColumns) + StartColumns(); + + int nBreakColumn = abTwoColumns ? (((OptionCount+1)>>1)-1) : (OptionCount+1); + int nFirstID = DialogItemsCount; + for(int i=0; iX2 = Item->X1 + ItemWidth(*Item); + if (i == 0) + Item->Flags |= DIF_GROUP; + if (*Value == i) + Item->Selected = TRUE; + if (AddFlags) + Item->Flags |= AddFlags; + SetLastItemBinding(CreateRadioButtonBinding(Value)); + if (i == nBreakColumn) + ColumnBreak(); + } + if (abTwoColumns) + EndColumns(); + return nFirstID; + } + + // Добавляет ComboBox + T* AddComboBox(int Width, FarList* ListItems, int *Value, DWORD AddFlags=DIF_DROPDOWNLIST) + { + T *Item = AddDialogItem(DI_COMBOBOX, nullptr); + for (int i = 0; i < ListItems->ItemsNumber; i++) + { + if (i == *Value) + ListItems->Items[i].Flags |= LIF_SELECTED; + else if (ListItems->Items[i].Flags & LIF_SELECTED) + ListItems->Items[i].Flags &= ~LIF_SELECTED; + } + Item->ListItems = ListItems; + Item->Flags |= AddFlags; + SetNextY(Item); + Item->X2 = Item->X1 + Width; + SetLastItemBinding(CreateComboBoxBinding(Value)); + return Item; + } + + // Добавляет поле типа DI_FIXEDIT для редактирования указанного числового значения. + virtual T* AddIntEditField(int *Value, int Width) + { + return nullptr; + } + + // Добавляет указанную текстовую строку слева от элемента RelativeTo. + T* AddTextBefore(T *RelativeTo, int LabelId) + { + T *Item = AddDialogItem(DI_TEXT, GetLangString(LabelId)); + Item->Y1 = Item->Y2 = RelativeTo->Y1; + Item->X1 = 5; + Item->X2 = Item->X1 + ItemWidth(*Item) - 1; + + int RelativeToWidth = RelativeTo->X2 - RelativeTo->X1; + RelativeTo->X1 = Item->X2 + 2; + RelativeTo->X2 = RelativeTo->X1 + RelativeToWidth; + + //// Текст должен идти первым элементом, чтобы хоткеи срабатывали + //T P; P = *RelativeTo; *RelativeTo = *Item; *Item = P; + //Item--; RelativeTo++; + + //int I1 = static_cast(Item - DialogItems); + //int I2 = static_cast(RelativeTo - DialogItems); + //DialogItemBinding *B1; + //B1 = Bindings[I1]; Bindings[I1] = Bindings[I2]; Bindings[I2] = B1; + + DialogItemBinding *Binding = FindBinding(RelativeTo); + if (Binding) + Binding->BeforeLabelID = GetItemID(Item); + + return Item; + } + + // Подвязать (a'la AddTextAfter) любой элемент к любому элементу + void MoveItemAfter(T *FirstItem, T *AfterItem) + { + int Width = ItemWidth(*AfterItem); + int Height = AfterItem->Y2 - AfterItem->Y1; + + AfterItem->Y1 = FirstItem->Y1; + AfterItem->Y2 = FirstItem->Y1 + Height; + AfterItem->X1 = FirstItem->X1 + ItemWidth(*FirstItem); + AfterItem->X2 = AfterItem->X1 + Width - 1; + + DialogItemBinding *Binding = FindBinding(AfterItem); + if (Binding) + { + Binding->BeforeLabelID = GetItemID(FirstItem); + _ASSERTE(Binding->BeforeLabelID != -1); + } + + NextY--; + } + + // Добавляет указанную текстовую строку справа от элемента RelativeTo. + T* AddTextAfter(T *RelativeTo, int LabelId) + { + T *Item = AddDialogItem(DI_TEXT, GetLangString(LabelId)); + Item->Y1 = Item->Y2 = RelativeTo->Y1; + Item->X1 = RelativeTo->X2 + 2; + + DialogItemBinding *Binding = FindBinding(RelativeTo); + if (Binding) + Binding->AfterLabelID = GetItemID(Item); + + return Item; + } + + // Начинает располагать поля диалога в две колонки. + void StartColumns() + { + ColumnStartIndex = DialogItemsCount; + ColumnStartY = NextY; + } + + // Завершает колонку полей в диалоге и переходит к следующей колонке. + void ColumnBreak() + { + ColumnBreakIndex = DialogItemsCount; + ColumnEndY = NextY; + NextY = ColumnStartY; + } + + // Завершает расположение полей диалога в две колонки. + void EndColumns() + { + for(int i=ColumnStartIndex; i *Binding = FindBinding(DialogItems + i); + int BindingAdd = 0; + if (Binding) { + if (Binding->BeforeLabelID != -1) + BindingAdd = ItemWidth(DialogItems [Binding->BeforeLabelID]) + 1; + else if (Binding->AfterLabelID != -1) + BindingAdd = ItemWidth(DialogItems [Binding->AfterLabelID]) + 1; + } + + if ((Width + BindingAdd) > ColumnMinWidth) + ColumnMinWidth = Width + BindingAdd; + if (i >= ColumnBreakIndex) + { + DialogItems [i].X1 = SECOND_COLUMN; + DialogItems [i].X2 = SECOND_COLUMN + Width; + } + } + + if (ColumnEndY > NextY) + NextY = ColumnEndY; + + ColumnStartIndex = -1; + ColumnBreakIndex = -1; + } + + // Добавляет пустую строку. + void AddEmptyLine() + { + NextY++; + } + + // Добавляет сепаратор. + void AddSeparator(int MessageId=-1) + { + T *Separator = AddDialogItem(DI_TEXT, MessageId == -1 ? EMPTY_TEXT : GetLangString(MessageId)); + Separator->Flags = DIF_SEPARATOR; + Separator->X1 = 3; + Separator->Y1 = Separator->Y2 = NextY++; + } + + // Добавляет сепаратор, кнопки OK и Cancel. + void AddOKCancel(int OKMessageId, int CancelMessageId) + { + AddSeparator(); + + T *OKButton = AddDialogItem(DI_BUTTON, GetLangString(OKMessageId)); + OKButton->Flags = DIF_CENTERGROUP; + OKButton->DefaultButton = TRUE; + OKButton->Y1 = OKButton->Y2 = NextY++; + OKButtonID = DialogItemsCount-1; + + T *CancelButton = AddDialogItem(DI_BUTTON, GetLangString(CancelMessageId)); + CancelButton->Flags = DIF_CENTERGROUP; + CancelButton->Y1 = CancelButton->Y2 = OKButton->Y1; + CancelButtonID = DialogItemsCount-1; + } + + void AddFooterButtons(int* BtnID, int nBtnCount) + { + AddSeparator(); + + for (int i = 0; i < nBtnCount; i++) + { + T *Button = AddDialogItem(DI_BUTTON, GetLangString(BtnID[i])); + Button->Flags = DIF_CENTERGROUP; + Button->DefaultButton = TRUE; + Button->Y1 = Button->Y2 = NextY; + if (i == 0) + OKButtonID = DialogItemsCount-1; + } + CancelButtonID = DialogItemsCount-1; + + NextY++; + } + + bool ShowDialog(int *pnBtnNo = NULL) + { + _ASSERTE(OKButtonID > 0 && OKButtonID < DialogItemsCount); + UpdateBorderSize(); + UpdateSecondColumnPosition(); + UpdateRightSlidePosition(); + int Result = DoShowDialog(); + if (Result >= OKButtonID && Result < CancelButtonID) + { + SaveValues(); + if (pnBtnNo) *pnBtnNo = (Result - OKButtonID); + return true; + } + return false; + } +}; + +class PluginDialogBuilder; + +class DialogAPIBinding: public DialogItemBinding +{ +protected: + const PluginStartupInfo &Info; + HANDLE *DialogHandle; + int ID; + + DialogAPIBinding(const PluginStartupInfo &aInfo, HANDLE *aHandle, int aID) + : Info(aInfo), DialogHandle(aHandle), ID(aID) + { + } +}; + +class PluginCheckBoxBinding: public DialogAPIBinding +{ + BOOL *Value; + int Mask; + +public: + PluginCheckBoxBinding(const PluginStartupInfo &aInfo, HANDLE *aHandle, int aID, BOOL *aValue, int aMask) + : DialogAPIBinding(aInfo, aHandle, aID), + Value(aValue), Mask(aMask) + { + } + + virtual void SaveValue(FarDialogItem *Item, int RadioGroupIndex) + { + BOOL Selected = static_cast(Info.SendDlgMessage(*DialogHandle, DM_GETCHECK, ID, 0)); + if (Mask == 0) + { + *Value = Selected; + } + else + { + if (Selected) + *Value |= Mask; + else + *Value &= ~Mask; + } + } +}; + +class PluginRadioButtonBinding: public DialogAPIBinding +{ + private: + int *Value; + + public: + PluginRadioButtonBinding(const PluginStartupInfo &aInfo, HANDLE *aHandle, int aID, int *aValue) + : DialogAPIBinding(aInfo, aHandle, aID), + Value(aValue) + { + } + + virtual void SaveValue(FarDialogItem *Item, int RadioGroupIndex) + { + if (Info.SendDlgMessage(*DialogHandle, DM_GETCHECK, ID, 0)) + *Value = RadioGroupIndex; + } +}; + +class PluginComboBoxBinding: public DialogAPIBinding +{ + private: + int *Value; + + public: + PluginComboBoxBinding(const PluginStartupInfo &aInfo, HANDLE *aHandle, int aID, int *aValue) + : DialogAPIBinding(aInfo, aHandle, aID), + Value(aValue) + { + } + + virtual void SaveValue(FarDialogItem *Item, int RadioGroupIndex) + { + *Value = (int)Info.SendDlgMessage(*DialogHandle, DM_LISTGETCURPOS, ID, 0); + } +}; + +#ifdef UNICODE + +class PluginEditFieldBinding: public DialogAPIBinding +{ +private: + TCHAR *Value; + int MaxSize; + +public: + PluginEditFieldBinding(const PluginStartupInfo &aInfo, HANDLE *aHandle, int aID, TCHAR *aValue, int aMaxSize) + : DialogAPIBinding(aInfo, aHandle, aID), Value(aValue), MaxSize(aMaxSize) + { + } + + virtual void SaveValue(FarDialogItem *Item, int RadioGroupIndex) + { + const TCHAR *DataPtr = (const TCHAR *) Info.SendDlgMessage(*DialogHandle, DM_GETCONSTTEXTPTR, ID, 0); + lstrcpyn(Value, DataPtr, MaxSize); + } +}; + +class PluginIntEditFieldBinding: public DialogAPIBinding +{ +private: + int *Value; + TCHAR Buffer[32]; + TCHAR Mask[32]; + +public: + PluginIntEditFieldBinding(const PluginStartupInfo &aInfo, HANDLE *aHandle, int aID, int *aValue, int Width) + : DialogAPIBinding(aInfo, aHandle, aID), + Value(aValue) + { + aInfo.FSF->itoa(*aValue, Buffer, 10); + int MaskWidth = Width < 31 ? Width : 31; + for(int i=0; iatoi(DataPtr); + } + + TCHAR* GetBuffer() + { + return Buffer; + } + + const TCHAR* GetMask() + { + return Mask; + } +}; + +#else + +class PluginEditFieldBinding: public DialogItemBinding +{ +private: + TCHAR *Value; + int MaxSize; + +public: + PluginEditFieldBinding(TCHAR *aValue, int aMaxSize) + : Value(aValue), MaxSize(aMaxSize) + { + } + + virtual void SaveValue(FarDialogItem *Item, int RadioGroupIndex) + { + lstrcpyn(Value, Item->Data, MaxSize); + } +}; + +class PluginIntEditFieldBinding: public DialogItemBinding +{ +private: + const PluginStartupInfo &Info; + int *Value; + TCHAR Mask[32]; + +public: + PluginIntEditFieldBinding(const PluginStartupInfo &aInfo, int *aValue, int Width) + : Info(aInfo), Value(aValue) + { + int MaskWidth = Width < 31 ? Width : 31; + for(int i=0; iatoi(Item->Data); + } + + const TCHAR* GetMask() + { + return Mask; + } +}; + +#endif + +/* +Версия класса для динамического построения диалогов, используемая в плагинах к FAR. +*/ +class PluginDialogBuilder: public DialogBuilderBase +{ + public: + DWORD DialogFlags; + protected: + const PluginStartupInfo &Info; + HANDLE DialogHandle; + const TCHAR *HelpTopic; + + virtual void InitDialogItem(FarDialogItem *Item, const TCHAR *Text) + { + memset(Item, 0, sizeof(FarDialogItem)); + if (Text) + { + #ifdef UNICODE + Item->PtrData = Text; + #else + lstrcpyn(Item->Data, Text, sizeof(Item->Data)/sizeof(Item->Data[0])); + #endif + } + } + + virtual int TextWidth(const FarDialogItem &Item) + { +#ifdef UNICODE + return lstrlen(Item.PtrData); +#else + return lstrlen(Item.Data); +#endif + } + + virtual const TCHAR* GetLangString(int MessageID) + { + return Info.GetMsg(Info.ModuleNumber, MessageID); + } + + virtual int DoShowDialog() + { + int Width = DialogItems [0].X2+4; + int Height = DialogItems [0].Y2+2; +#ifdef UNICODE + DialogHandle = Info.DialogInit(Info.ModuleNumber, -1, -1, Width, Height, + HelpTopic, DialogItems, DialogItemsCount, 0, DialogFlags, nullptr, 0); + return Info.DialogRun(DialogHandle); +#else + return Info.DialogEx(Info.ModuleNumber, -1, -1, Width, Height, + HelpTopic, DialogItems, DialogItemsCount, 0, DialogFlags, nullptr, 0); +#endif + } + + virtual DialogItemBinding* CreateCheckBoxBinding(BOOL *Value, int Mask) + { +#ifdef UNICODE + return new PluginCheckBoxBinding(Info, &DialogHandle, DialogItemsCount-1, Value, Mask); +#else + return new CheckBoxBinding(Value, Mask); +#endif + } + + virtual DialogItemBinding* CreateRadioButtonBinding(BOOL *Value) + { +#ifdef UNICODE + return new PluginRadioButtonBinding(Info, &DialogHandle, DialogItemsCount-1, Value); +#else + return new RadioButtonBinding(Value); +#endif + } + + virtual DialogItemBinding* CreateComboBoxBinding(int *Value) + { +#ifdef UNICODE + return new PluginComboBoxBinding(Info, &DialogHandle, DialogItemsCount-1, Value); +#else + return new PluginComboBoxBinding(Value); +#endif + } + +public: + PluginDialogBuilder(const PluginStartupInfo &aInfo, int TitleMessageID, const TCHAR *aHelpTopic) + : DialogFlags(0), Info(aInfo), DialogHandle(NULL), HelpTopic(aHelpTopic) + { + AddBorder(GetLangString(TitleMessageID)); + } + + ~PluginDialogBuilder() + { +#ifdef UNICODE + if (DialogHandle) + { + Info.DialogFree(DialogHandle); + DialogHandle = NULL; + } +#endif + } + + FarDialogItem* GetItemByIndex(int Index) + { + if (Index >= 0 && Index < DialogItemsCount) + return (DialogItems + Index); + return NULL; + } + + int GetItemIndex(FarDialogItem* p) + { + return GetItemID(p); + } + + virtual FarDialogItem* AddIntEditField(int *Value, int Width) + { + FarDialogItem *Item = AddDialogItem(DI_FIXEDIT, EMPTY_TEXT); + Item->Flags |= DIF_MASKEDIT; + PluginIntEditFieldBinding *Binding; +#ifdef UNICODE + Binding = new PluginIntEditFieldBinding(Info, &DialogHandle, DialogItemsCount-1, Value, Width); + Item->PtrData = Binding->GetBuffer(); +#else + Binding = new PluginIntEditFieldBinding(Info, Value, Width); + Info.FSF->itoa(*Value, (TCHAR *) Item->Data, 10); +#endif + + +#ifdef _FAR_NO_NAMELESS_UNIONS + Item->Param.Mask = Binding->GetMask(); +#else + Item->Mask = Binding->GetMask(); +#endif + SetNextY(Item); + Item->X2 = Item->X1 + Width - 1; + SetLastItemBinding(Binding); + return Item; + } + + FarDialogItem* AddEditField(TCHAR *Value, int MaxSize, int Width, const TCHAR *HistoryID = nullptr) + { + FarDialogItem *Item = AddDialogItem(DI_EDIT, Value); + SetNextY(Item); + Item->X2 = Item->X1 + Width; + if (HistoryID) + { +#ifdef _FAR_NO_NAMELESS_UNIONS + Item->Param.History = HistoryID; +#else + Item->History = HistoryID; +#endif + Item->Flags |= DIF_HISTORY; + } + +#ifdef UNICODE + SetLastItemBinding(new PluginEditFieldBinding(Info, &DialogHandle, DialogItemsCount-1, Value, MaxSize)); +#else + SetLastItemBinding(new PluginEditFieldBinding(Value, MaxSize)); +#endif + return Item; + } +}; diff --git a/Uninstall/src/EPlugin.cpp b/Uninstall/src/EPlugin.cpp index 8840260..a4b35d0 100644 --- a/Uninstall/src/EPlugin.cpp +++ b/Uninstall/src/EPlugin.cpp @@ -3,89 +3,93 @@ static struct FarStandardFunctions FSF; const TCHAR* GetMsg(int MsgId) { - return(Info.GetMsg(Info.ModuleNumber,MsgId)); + return(Info.GetMsg(Info.ModuleNumber,MsgId)); } void ShowHelp(const TCHAR * HelpTopic) { - Info.ShowHelp(Info.ModuleName,HelpTopic,0); + Info.ShowHelp(Info.ModuleName,HelpTopic,0); } int EMessage(const TCHAR * const * s, int nType, int n) { - return Info.Message(Info.ModuleNumber, FMSG_ALLINONE|nType, NULL, s, - 0, //нв®в Ї а ¬Ґва ЇаЁ FMSG_ALLINONE ЁЈ­®аЁагҐвбп - n); //Є®«ЁзҐбвў® Є­®Ї®Є + return Info.Message(Info.ModuleNumber, FMSG_ALLINONE|nType, NULL, s, + 0, //нв®в Ї а ¬Ґва ЇаЁ FMSG_ALLINONE ЁЈ­®аЁагҐвбп + n); //Є®«ЁзҐбвў® Є­®Ї®Є } int DrawMessage(int nType, int n, char *msg, ...) { - int total = 0; - TCHAR * string = NULL; + int total = 0; + TCHAR * string = NULL; + va_list ap; + TCHAR * arg; + va_start(ap, msg); - va_list ap; - TCHAR * arg; + while((arg = va_arg(ap,TCHAR*))!= 0) + { + total += lstrlen(arg) + 1; //¬л ҐйҐ Ўг¤Ґ¬ § ЇЁблў вм бЁ¬ў®« ЇҐаҐў®¤  бва®ЄЁ + } - va_start(ap, msg); - while ((arg = va_arg(ap,TCHAR*))!= 0) - { - total += lstrlen(arg) + 1; //¬л ҐйҐ Ўг¤Ґ¬ § ЇЁблў вм бЁ¬ў®« ЇҐаҐў®¤  бва®ЄЁ - } - va_end(ap); + va_end(ap); + total--; //Ї®б«Ґ¤­Ё© §­ Є ЇҐаҐў®¤  бва®ЄЁ ¬л б®в६ + string = (TCHAR *) realloc(string, sizeof(TCHAR)*(total + 1)); + string[0]=_T('\0'); + va_start(ap, msg); - total--; //Ї®б«Ґ¤­Ё© §­ Є ЇҐаҐў®¤  бва®ЄЁ ¬л б®в६ + while((arg = va_arg(ap,TCHAR*))!= NULL) + { + StringCchCat(string, total+1, arg); + StringCchCat(string, total+1, _T("\n")); + } - string = (TCHAR *) realloc(string, sizeof(TCHAR)*(total + 1)); - - string[0]=_T('\0'); - - va_start(ap, msg); - while ((arg = va_arg(ap,TCHAR*))!= NULL) - { - StringCchCat(string, total+1, arg); - StringCchCat(string, total+1, _T("\n")); - } - va_end(ap); - - string[total]=_T('\0'); - - int result = EMessage((const TCHAR * const *) string, nType, n); - realloc(string, 0); - return result; + va_end(ap); + string[total]=_T('\0'); + int result = EMessage((const TCHAR * const *) string, nType, n); + realloc(string, 0); + return result; } const TCHAR * strstri(const TCHAR *s, const TCHAR *c) { - if (c) - { - int l = lstrlen(c); - for (const TCHAR *p = s ; *p ; p++) - if (FSF.LStrnicmp(p, c, l) == 0) - return p; - } - return NULL; + if(c) + { + int l = lstrlen(c); + + for(const TCHAR *p = s ; *p ; p++) + if(FSF.LStrnicmp(p, c, l) == 0) + return p; + } + + return NULL; } TCHAR * strnstri(TCHAR *s, const TCHAR *c, int n) { - if (c) - { - int l = min(lstrlen(c), n); - for (TCHAR *p = s ; *p ; p++) - if (FSF.LStrnicmp(p, c, l) == 0) - return p; - } - return NULL; + if(c) + { + int l = min(lstrlen(c), n); + + for(TCHAR *p = s ; *p ; p++) + if(FSF.LStrnicmp(p, c, l) == 0) + return p; + } + + return NULL; } TCHAR * unQuote(TCHAR *vStr) { - unsigned l; - l = lstrlen(vStr); - if (*vStr == _T('\"')) - memmove(vStr,vStr+1,l*sizeof(TCHAR)); - l = lstrlen(vStr); - if (vStr[l-1] == _T('\"')) - vStr[l-1] = _T('\0'); - return(vStr); + unsigned l; + l = lstrlen(vStr); + + if(*vStr == _T('\"')) + memmove(vStr,vStr+1,l*sizeof(TCHAR)); + + l = lstrlen(vStr); + + if(vStr[l-1] == _T('\"')) + vStr[l-1] = _T('\0'); + + return(vStr); } diff --git a/Uninstall/src/EPlugin.cpp.orig b/Uninstall/src/EPlugin.cpp.orig new file mode 100644 index 0000000..8840260 --- /dev/null +++ b/Uninstall/src/EPlugin.cpp.orig @@ -0,0 +1,91 @@ +static struct PluginStartupInfo Info; +static struct FarStandardFunctions FSF; + +const TCHAR* GetMsg(int MsgId) +{ + return(Info.GetMsg(Info.ModuleNumber,MsgId)); +} + +void ShowHelp(const TCHAR * HelpTopic) +{ + Info.ShowHelp(Info.ModuleName,HelpTopic,0); +} + +int EMessage(const TCHAR * const * s, int nType, int n) +{ + return Info.Message(Info.ModuleNumber, FMSG_ALLINONE|nType, NULL, s, + 0, //нв®в Ї а ¬Ґва ЇаЁ FMSG_ALLINONE ЁЈ­®аЁагҐвбп + n); //Є®«ЁзҐбвў® Є­®Ї®Є +} + +int DrawMessage(int nType, int n, char *msg, ...) +{ + int total = 0; + TCHAR * string = NULL; + + va_list ap; + TCHAR * arg; + + va_start(ap, msg); + while ((arg = va_arg(ap,TCHAR*))!= 0) + { + total += lstrlen(arg) + 1; //¬л ҐйҐ Ўг¤Ґ¬ § ЇЁблў вм бЁ¬ў®« ЇҐаҐў®¤  бва®ЄЁ + } + va_end(ap); + + total--; //Ї®б«Ґ¤­Ё© §­ Є ЇҐаҐў®¤  бва®ЄЁ ¬л б®в६ + + string = (TCHAR *) realloc(string, sizeof(TCHAR)*(total + 1)); + + string[0]=_T('\0'); + + va_start(ap, msg); + while ((arg = va_arg(ap,TCHAR*))!= NULL) + { + StringCchCat(string, total+1, arg); + StringCchCat(string, total+1, _T("\n")); + } + va_end(ap); + + string[total]=_T('\0'); + + int result = EMessage((const TCHAR * const *) string, nType, n); + realloc(string, 0); + return result; +} + +const TCHAR * strstri(const TCHAR *s, const TCHAR *c) +{ + if (c) + { + int l = lstrlen(c); + for (const TCHAR *p = s ; *p ; p++) + if (FSF.LStrnicmp(p, c, l) == 0) + return p; + } + return NULL; +} + +TCHAR * strnstri(TCHAR *s, const TCHAR *c, int n) +{ + if (c) + { + int l = min(lstrlen(c), n); + for (TCHAR *p = s ; *p ; p++) + if (FSF.LStrnicmp(p, c, l) == 0) + return p; + } + return NULL; +} + +TCHAR * unQuote(TCHAR *vStr) +{ + unsigned l; + l = lstrlen(vStr); + if (*vStr == _T('\"')) + memmove(vStr,vStr+1,l*sizeof(TCHAR)); + l = lstrlen(vStr); + if (vStr[l-1] == _T('\"')) + vStr[l-1] = _T('\0'); + return(vStr); +} diff --git a/Uninstall/src/Registry.cpp b/Uninstall/src/Registry.cpp index 5f3c286..49ddcfb 100644 --- a/Uninstall/src/Registry.cpp +++ b/Uninstall/src/Registry.cpp @@ -19,139 +19,152 @@ HKEY OpenRegKey(HKEY hRoot,TCHAR *Key); // ¤«п §­ зҐ­Ёп б Ё¬Ґ­Ґ¬ ValueName гбв ­®ўЁвм §­ зҐ­ЁҐ вЁЇ  char* void SetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,TCHAR *ValueData) { - HKEY hKey=CreateRegKey(hRoot,Key); - RegSetValueEx(hKey,ValueName,0,REG_SZ,(const BYTE*)ValueData,(lstrlen(ValueData)+1)*sizeof(TCHAR)); - RegCloseKey(hKey); + HKEY hKey=CreateRegKey(hRoot,Key); + RegSetValueEx(hKey,ValueName,0,REG_SZ,(const BYTE*)ValueData,(lstrlen(ValueData)+1)*sizeof(TCHAR)); + RegCloseKey(hKey); } // гбв ­®ўЁвм §­ зҐ­ЁҐ вЁЇ  DWORD void SetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,DWORD ValueData) { - HKEY hKey=CreateRegKey(hRoot,Key); - RegSetValueEx(hKey,ValueName,0,REG_DWORD,(BYTE *)&ValueData,sizeof(ValueData)); - RegCloseKey(hKey); + HKEY hKey=CreateRegKey(hRoot,Key); + RegSetValueEx(hKey,ValueName,0,REG_DWORD,(BYTE *)&ValueData,sizeof(ValueData)); + RegCloseKey(hKey); } // гбв ­®ўЁвм §­ зҐ­ЁҐ вЁЇ  Binary void SetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,BYTE *ValueData,DWORD ValueSize) { - HKEY hKey=CreateRegKey(hRoot,Key); - RegSetValueEx(hKey,ValueName,0,REG_BINARY,ValueData,ValueSize); - RegCloseKey(hKey); + HKEY hKey=CreateRegKey(hRoot,Key); + RegSetValueEx(hKey,ValueName,0,REG_BINARY,ValueData,ValueSize); + RegCloseKey(hKey); } // Ї®«гзЁвм ¤ ­­лҐ вЁЇ  char* int GetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,TCHAR *ValueData,TCHAR *Default,DWORD DataSize) { - HKEY hKey=OpenRegKey(hRoot,Key); - DWORD Type; - DWORD Size = DataSize * sizeof(TCHAR); - int ExitCode=RegQueryValueEx(hKey,ValueName,0,&Type,(LPBYTE)ValueData,&Size); - ValueData[DataSize - 1] = 0; - RegCloseKey(hKey); - if (hKey==NULL || ExitCode!=ERROR_SUCCESS) - { - StringCchCopy(ValueData,DataSize,Default); - return(FALSE); - } - return(TRUE); + HKEY hKey=OpenRegKey(hRoot,Key); + DWORD Type; + DWORD Size = DataSize * sizeof(TCHAR); + int ExitCode=RegQueryValueEx(hKey,ValueName,0,&Type,(LPBYTE)ValueData,&Size); + ValueData[DataSize - 1] = 0; + RegCloseKey(hKey); + + if(hKey==NULL || ExitCode!=ERROR_SUCCESS) + { + StringCchCopy(ValueData,DataSize,Default); + return(FALSE); + } + + return(TRUE); } // Ї®«гзЁвм ¤ ­­лҐ вЁЇ  DWORD int GetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,int &ValueData,DWORD Default) { - HKEY hKey=OpenRegKey(hRoot,Key); - DWORD Type,Size=sizeof(ValueData); - int ExitCode=RegQueryValueEx(hKey,ValueName,0,&Type,(BYTE *)&ValueData,&Size); - RegCloseKey(hKey); - if (hKey==NULL || ExitCode!=ERROR_SUCCESS) - { - ValueData=Default; - return(FALSE); - } - return(TRUE); + HKEY hKey=OpenRegKey(hRoot,Key); + DWORD Type,Size=sizeof(ValueData); + int ExitCode=RegQueryValueEx(hKey,ValueName,0,&Type,(BYTE *)&ValueData,&Size); + RegCloseKey(hKey); + + if(hKey==NULL || ExitCode!=ERROR_SUCCESS) + { + ValueData=Default; + return(FALSE); + } + + return(TRUE); } // Ї®«гзЁвм ¤ ­­лҐ вЁЇ  DWORD int GetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,DWORD Default) { - int ValueData; - GetRegKey(hRoot,Key,ValueName,ValueData,Default); - return(ValueData); + int ValueData; + GetRegKey(hRoot,Key,ValueName,ValueData,Default); + return(ValueData); } // Ї®«гзЁвм ¤ ­­лҐ вЁЇ  Binary int GetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,BYTE *ValueData,BYTE *Default,DWORD DataSize) { - HKEY hKey=OpenRegKey(hRoot,Key); - DWORD Type; - int ExitCode=RegQueryValueEx(hKey,ValueName,0,&Type,ValueData,&DataSize); - RegCloseKey(hKey); - if (hKey==NULL || ExitCode!=ERROR_SUCCESS) - { - if (Default!=NULL) - memcpy(ValueData,Default,DataSize); - else - memset(ValueData,0,DataSize); - return(FALSE); - } - return(TRUE); + HKEY hKey=OpenRegKey(hRoot,Key); + DWORD Type; + int ExitCode=RegQueryValueEx(hKey,ValueName,0,&Type,ValueData,&DataSize); + RegCloseKey(hKey); + + if(hKey==NULL || ExitCode!=ERROR_SUCCESS) + { + if(Default!=NULL) + memcpy(ValueData,Default,DataSize); + else + memset(ValueData,0,DataSize); + + return(FALSE); + } + + return(TRUE); } // г¤ «пҐв Є«оз void DeleteRegKey(HKEY hRoot,TCHAR *Key) { - TCHAR FullKeyName[512]; - StringCchCopy(FullKeyName,ARRAYSIZE(FullKeyName),PluginRootKey); - StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),(Key && *Key ? _T("\\"):_T(""))); - StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),Key); - RegDeleteKey(hRoot,FullKeyName); + TCHAR FullKeyName[512]; + StringCchCopy(FullKeyName,ARRAYSIZE(FullKeyName),PluginRootKey); + StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),(Key && *Key ? _T("\\"):_T(""))); + StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),Key); + RegDeleteKey(hRoot,FullKeyName); } // ᮧ¤ вм Є«оз HKEY CreateRegKey(HKEY hRoot,TCHAR *Key) { - HKEY hKey; - DWORD Disposition; - TCHAR FullKeyName[512]; - StringCchCopy(FullKeyName,ARRAYSIZE(FullKeyName),PluginRootKey); - StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),(Key && *Key ? _T("\\"):_T(""))); - StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),Key); - if(RegCreateKeyEx(hRoot,FullKeyName,0,NULL,0,KEY_WRITE,NULL, - &hKey,&Disposition) != ERROR_SUCCESS) - hKey=NULL; - return(hKey); + HKEY hKey; + DWORD Disposition; + TCHAR FullKeyName[512]; + StringCchCopy(FullKeyName,ARRAYSIZE(FullKeyName),PluginRootKey); + StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),(Key && *Key ? _T("\\"):_T(""))); + StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),Key); + + if(RegCreateKeyEx(hRoot,FullKeyName,0,NULL,0,KEY_WRITE,NULL, + &hKey,&Disposition) != ERROR_SUCCESS) + hKey=NULL; + + return(hKey); } // ®вЄалвм § ¤ ­­го ўҐвўм ॥бва  HKEY OpenRegKey(HKEY hRoot,TCHAR *Key) { - HKEY hKey; - TCHAR FullKeyName[512]; - StringCchCopy(FullKeyName,ARRAYSIZE(FullKeyName),PluginRootKey); - StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),(Key && *Key ? _T("\\"):_T(""))); - StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),Key); - if (RegOpenKeyEx(hRoot,FullKeyName,0,KEY_QUERY_VALUE,&hKey)!=ERROR_SUCCESS) - return(NULL); - return(hKey); + HKEY hKey; + TCHAR FullKeyName[512]; + StringCchCopy(FullKeyName,ARRAYSIZE(FullKeyName),PluginRootKey); + StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),(Key && *Key ? _T("\\"):_T(""))); + StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),Key); + + if(RegOpenKeyEx(hRoot,FullKeyName,0,KEY_QUERY_VALUE,&hKey)!=ERROR_SUCCESS) + return(NULL); + + return(hKey); } // Їа®ўҐаЁвм бгйҐбвў®ў ­ЁҐ Є«оз  BOOL CheckRegKey(HKEY hRoot,TCHAR *Key) { - HKEY hKey=OpenRegKey(hRoot,Key); - if (hKey!=NULL) - RegCloseKey(hKey); - return(hKey!=NULL); + HKEY hKey=OpenRegKey(hRoot,Key); + + if(hKey!=NULL) + RegCloseKey(hKey); + + return(hKey!=NULL); } #endif diff --git a/Uninstall/src/Registry.cpp.orig b/Uninstall/src/Registry.cpp.orig new file mode 100644 index 0000000..5f3c286 --- /dev/null +++ b/Uninstall/src/Registry.cpp.orig @@ -0,0 +1,157 @@ +TCHAR PluginRootKey[80]; + +#define HKCU HKEY_CURRENT_USER +#define HKCR HKEY_CLASSES_ROOT +#define HKCC HKEY_CURRENT_CONFIG +#define HKLM HKEY_LOCAL_MACHINE +#define HKU HKEY_USERS + +/* + ”г­ЄжЁЁ а Ў®вл б ॥бв஬ + ’ॡгҐвбп ў­Ґи­пп ЇҐаҐ¬Ґ­­ п PluginRootKey +*/ + +#ifdef __cplusplus + +HKEY CreateRegKey(HKEY hRoot,TCHAR *Key); +HKEY OpenRegKey(HKEY hRoot,TCHAR *Key); + +// ¤«п §­ зҐ­Ёп б Ё¬Ґ­Ґ¬ ValueName гбв ­®ўЁвм §­ зҐ­ЁҐ вЁЇ  char* +void SetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,TCHAR *ValueData) +{ + HKEY hKey=CreateRegKey(hRoot,Key); + RegSetValueEx(hKey,ValueName,0,REG_SZ,(const BYTE*)ValueData,(lstrlen(ValueData)+1)*sizeof(TCHAR)); + RegCloseKey(hKey); +} + + +// гбв ­®ўЁвм §­ зҐ­ЁҐ вЁЇ  DWORD +void SetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,DWORD ValueData) +{ + HKEY hKey=CreateRegKey(hRoot,Key); + RegSetValueEx(hKey,ValueName,0,REG_DWORD,(BYTE *)&ValueData,sizeof(ValueData)); + RegCloseKey(hKey); +} + + +// гбв ­®ўЁвм §­ зҐ­ЁҐ вЁЇ  Binary +void SetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,BYTE *ValueData,DWORD ValueSize) +{ + HKEY hKey=CreateRegKey(hRoot,Key); + RegSetValueEx(hKey,ValueName,0,REG_BINARY,ValueData,ValueSize); + RegCloseKey(hKey); +} + + +// Ї®«гзЁвм ¤ ­­лҐ вЁЇ  char* +int GetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,TCHAR *ValueData,TCHAR *Default,DWORD DataSize) +{ + HKEY hKey=OpenRegKey(hRoot,Key); + DWORD Type; + DWORD Size = DataSize * sizeof(TCHAR); + int ExitCode=RegQueryValueEx(hKey,ValueName,0,&Type,(LPBYTE)ValueData,&Size); + ValueData[DataSize - 1] = 0; + RegCloseKey(hKey); + if (hKey==NULL || ExitCode!=ERROR_SUCCESS) + { + StringCchCopy(ValueData,DataSize,Default); + return(FALSE); + } + return(TRUE); +} + + +// Ї®«гзЁвм ¤ ­­лҐ вЁЇ  DWORD +int GetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,int &ValueData,DWORD Default) +{ + HKEY hKey=OpenRegKey(hRoot,Key); + DWORD Type,Size=sizeof(ValueData); + int ExitCode=RegQueryValueEx(hKey,ValueName,0,&Type,(BYTE *)&ValueData,&Size); + RegCloseKey(hKey); + if (hKey==NULL || ExitCode!=ERROR_SUCCESS) + { + ValueData=Default; + return(FALSE); + } + return(TRUE); +} + + +// Ї®«гзЁвм ¤ ­­лҐ вЁЇ  DWORD +int GetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,DWORD Default) +{ + int ValueData; + GetRegKey(hRoot,Key,ValueName,ValueData,Default); + return(ValueData); +} + + +// Ї®«гзЁвм ¤ ­­лҐ вЁЇ  Binary +int GetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,BYTE *ValueData,BYTE *Default,DWORD DataSize) +{ + HKEY hKey=OpenRegKey(hRoot,Key); + DWORD Type; + int ExitCode=RegQueryValueEx(hKey,ValueName,0,&Type,ValueData,&DataSize); + RegCloseKey(hKey); + if (hKey==NULL || ExitCode!=ERROR_SUCCESS) + { + if (Default!=NULL) + memcpy(ValueData,Default,DataSize); + else + memset(ValueData,0,DataSize); + return(FALSE); + } + return(TRUE); +} + + +// г¤ «пҐв Є«оз +void DeleteRegKey(HKEY hRoot,TCHAR *Key) +{ + TCHAR FullKeyName[512]; + StringCchCopy(FullKeyName,ARRAYSIZE(FullKeyName),PluginRootKey); + StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),(Key && *Key ? _T("\\"):_T(""))); + StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),Key); + RegDeleteKey(hRoot,FullKeyName); +} + + +// ᮧ¤ вм Є«оз +HKEY CreateRegKey(HKEY hRoot,TCHAR *Key) +{ + HKEY hKey; + DWORD Disposition; + TCHAR FullKeyName[512]; + StringCchCopy(FullKeyName,ARRAYSIZE(FullKeyName),PluginRootKey); + StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),(Key && *Key ? _T("\\"):_T(""))); + StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),Key); + if(RegCreateKeyEx(hRoot,FullKeyName,0,NULL,0,KEY_WRITE,NULL, + &hKey,&Disposition) != ERROR_SUCCESS) + hKey=NULL; + return(hKey); +} + + +// ®вЄалвм § ¤ ­­го ўҐвўм ॥бва  +HKEY OpenRegKey(HKEY hRoot,TCHAR *Key) +{ + HKEY hKey; + TCHAR FullKeyName[512]; + StringCchCopy(FullKeyName,ARRAYSIZE(FullKeyName),PluginRootKey); + StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),(Key && *Key ? _T("\\"):_T(""))); + StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),Key); + if (RegOpenKeyEx(hRoot,FullKeyName,0,KEY_QUERY_VALUE,&hKey)!=ERROR_SUCCESS) + return(NULL); + return(hKey); +} + +// Їа®ўҐаЁвм бгйҐбвў®ў ­ЁҐ Є«оз  +BOOL CheckRegKey(HKEY hRoot,TCHAR *Key) +{ + HKEY hKey=OpenRegKey(hRoot,Key); + if (hKey!=NULL) + RegCloseKey(hKey); + return(hKey!=NULL); +} + +#endif diff --git a/Uninstall/src/UnInstall.cpp b/Uninstall/src/UnInstall.cpp index 2332920..08ec546 100644 --- a/Uninstall/src/UnInstall.cpp +++ b/Uninstall/src/UnInstall.cpp @@ -7,10 +7,10 @@ #include "memory.h" #define realloc my_realloc #ifndef nullptr - #define nullptr NULL +#define nullptr NULL #endif #ifndef _ASSERTE - #define _ASSERTE(x) +#define _ASSERTE(x) #endif #include "DlgBuilder.hpp" #include "eplugin.cpp" @@ -30,513 +30,520 @@ #ifdef FARAPI17 int WINAPI GetMinFarVersion(void) { - return MAKEFARVERSION(1,75,2555); + return MAKEFARVERSION(1,75,2555); } #endif #ifdef FARAPI18 int WINAPI GetMinFarVersion(void) { - return FARMANAGERVERSION; + return FARMANAGERVERSION; } int WINAPI GetMinFarVersionW(void) { - return FARMANAGERVERSION; + return FARMANAGERVERSION; } #endif void WINAPI SetStartupInfo(const struct PluginStartupInfo *psInfo) { - Info = *psInfo; - FSF = *psInfo->FSF; - Info.FSF = &FSF; - InitHeap(); - StringCchCopy(PluginRootKey,ARRAYSIZE(PluginRootKey),Info.RootKey); - StringCchCat(PluginRootKey,ARRAYSIZE(PluginRootKey),_T("\\UnInstall")); - ReadRegistry(); + Info = *psInfo; + FSF = *psInfo->FSF; + Info.FSF = &FSF; + InitHeap(); + StringCchCopy(PluginRootKey,ARRAYSIZE(PluginRootKey),Info.RootKey); + StringCchCat(PluginRootKey,ARRAYSIZE(PluginRootKey),_T("\\UnInstall")); + ReadRegistry(); } void WINAPI GetPluginInfo(struct PluginInfo *Info) { - static const TCHAR *PluginMenuStrings[1]; - PluginMenuStrings[0] = GetMsg(MPlugIn); - Info -> StructSize = sizeof(*Info); - Info -> PluginMenuStrings = PluginMenuStrings; - Info -> PluginConfigStrings = PluginMenuStrings; - if (Opt.WhereWork & 2) - Info -> Flags |= PF_EDITOR; - if (Opt.WhereWork & 1) - Info -> Flags |= PF_VIEWER; - Info -> PluginMenuStringsNumber = ARRAYSIZE(PluginMenuStrings); - Info -> PluginConfigStringsNumber = ARRAYSIZE(PluginMenuStrings); + static const TCHAR *PluginMenuStrings[1]; + PluginMenuStrings[0] = GetMsg(MPlugIn); + Info -> StructSize = sizeof(*Info); + Info -> PluginMenuStrings = PluginMenuStrings; + Info -> PluginConfigStrings = PluginMenuStrings; + + if(Opt.WhereWork & 2) + Info -> Flags |= PF_EDITOR; + + if(Opt.WhereWork & 1) + Info -> Flags |= PF_VIEWER; + + Info -> PluginMenuStringsNumber = ARRAYSIZE(PluginMenuStrings); + Info -> PluginConfigStringsNumber = ARRAYSIZE(PluginMenuStrings); } -void ResizeDialog(HANDLE hDlg) { - CONSOLE_SCREEN_BUFFER_INFO con_info; - GetConsoleScreenBufferInfo(hStdout, &con_info); - unsigned con_sx = con_info.srWindow.Right - con_info.srWindow.Left + 1; - int max_items = con_info.srWindow.Bottom - con_info.srWindow.Top + 1 - 7; - int s = ((ListSize>0) && (ListSize0 ? max_items : 0)); - SMALL_RECT NewPos = { 2, 1, con_sx - 7, s + 2 }; - SMALL_RECT OldPos; - Info.SendDlgMessage(hDlg,DM_GETITEMPOSITION,LIST_BOX,reinterpret_cast(&OldPos)); - if (NewPos.Right!=OldPos.Right || NewPos.Bottom!=OldPos.Bottom) { - COORD coord; - coord.X = con_sx - 4; - coord.Y = s + 4; - Info.SendDlgMessage(hDlg,DM_RESIZEDIALOG,0,reinterpret_cast(&coord)); - coord.X = -1; - coord.Y = -1; - Info.SendDlgMessage(hDlg,DM_MOVEDIALOG,TRUE,reinterpret_cast(&coord)); - Info.SendDlgMessage(hDlg,DM_SETITEMPOSITION,LIST_BOX,reinterpret_cast(&NewPos)); - } +void ResizeDialog(HANDLE hDlg) +{ + CONSOLE_SCREEN_BUFFER_INFO con_info; + GetConsoleScreenBufferInfo(hStdout, &con_info); + unsigned con_sx = con_info.srWindow.Right - con_info.srWindow.Left + 1; + int max_items = con_info.srWindow.Bottom - con_info.srWindow.Top + 1 - 7; + int s = ((ListSize>0) && (ListSize0 ? max_items : 0)); + SMALL_RECT NewPos = { 2, 1, con_sx - 7, s + 2 }; + SMALL_RECT OldPos; + Info.SendDlgMessage(hDlg,DM_GETITEMPOSITION,LIST_BOX,reinterpret_cast(&OldPos)); + + if(NewPos.Right!=OldPos.Right || NewPos.Bottom!=OldPos.Bottom) + { + COORD coord; + coord.X = con_sx - 4; + coord.Y = s + 4; + Info.SendDlgMessage(hDlg,DM_RESIZEDIALOG,0,reinterpret_cast(&coord)); + coord.X = -1; + coord.Y = -1; + Info.SendDlgMessage(hDlg,DM_MOVEDIALOG,TRUE,reinterpret_cast(&coord)); + Info.SendDlgMessage(hDlg,DM_SETITEMPOSITION,LIST_BOX,reinterpret_cast(&NewPos)); + } } static LONG_PTR WINAPI DlgProc(HANDLE hDlg,int Msg,int Param1,LONG_PTR Param2) { - static TCHAR Filter[MAX_PATH]; - static TCHAR spFilter[MAX_PATH]; - static FarListTitles ListTitle; - - switch(Msg) - { - case DN_RESIZECONSOLE: - { - Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,FALSE,0); - ResizeDialog(hDlg); - Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,TRUE,0); - } - return TRUE; - - case DMU_UPDATE: - { - int OldPos = static_cast(Info.SendDlgMessage(hDlg,DM_LISTGETCURPOS,LIST_BOX,0)); - - if (Param1) - UpDateInfo(); - - ListSize = 0; - int NewPos = -1; - if (OldPos >= 0 && OldPos < nCount) - { - if (!*Filter || strstri(p[OldPos].Keys[DisplayName],Filter)) //без учета регистра в OEM кодировке - NewPos = OldPos; - } - for (int i = 0; i < nCount; i++) - { - const TCHAR* DispName = p[i].Keys[DisplayName], *Find; - if (*Filter) - Find = strstri(DispName,Filter); - else - Find = DispName; - if (Find != nullptr) //без учета регистра в OEM кодировке - { - FLI[i].Flags &= ~LIF_HIDDEN; - if (Param2 && (i == OldPos)) - { - if (FLI[i].Flags & LIF_CHECKED) - { - FLI[i].Flags &= ~LIF_CHECKED; - } - else - { - FLI[i].Flags |= LIF_CHECKED; - } - } - //без учета регистра - а кодировка ANSI - if (NewPos == -1 && Find == DispName) - NewPos = i; - ListSize++; - } - else - FLI[i].Flags |= LIF_HIDDEN; - } - if (Param1 == 0 && Param2) - { - // Снятие или установка пометки (Ins) - if (Param2 == 1) - { - for (int i = (OldPos+1); i < nCount; i++) - { - if (!(FLI[i].Flags & LIF_HIDDEN)) - { - OldPos = i; break; - } - } - NewPos = OldPos; - } - // Снятие или установка пометки (RClick) - else if (Param2 == 2) - { - NewPos = OldPos; - } - } - else if (NewPos == -1) - { - NewPos = OldPos; - } - - Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,FALSE,0); - - Info.SendDlgMessage(hDlg,DM_LISTSET,LIST_BOX,reinterpret_cast(&FL)); - - StringCchPrintf(spFilter,ARRAYSIZE(spFilter), GetMsg(MFilter),Filter,ListSize,nCount); - ListTitle.Title = spFilter; - ListTitle.TitleLen = lstrlen(spFilter); - Info.SendDlgMessage(hDlg,DM_LISTSETTITLES,LIST_BOX,reinterpret_cast(&ListTitle)); - - ResizeDialog(hDlg); - - struct FarListPos FLP; - FLP.SelectPos = NewPos; - FLP.TopPos = -1; - Info.SendDlgMessage(hDlg,DM_LISTSETCURPOS,LIST_BOX,reinterpret_cast(&FLP)); - - Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,TRUE,0); - } - break; - - case DN_INITDIALOG: - { - StringCchCopy(Filter,ARRAYSIZE(Filter),_T("")); - ListTitle.Bottom = const_cast(GetMsg(MBottomLine)); - ListTitle.BottomLen = lstrlen(GetMsg(MBottomLine)); - - //подстраиваемся под размеры консоли - Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,FALSE,0); - ResizeDialog(hDlg); - Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,TRUE,0); - //заполняем диалог - Info.SendDlgMessage(hDlg,DMU_UPDATE,1,0); - } - break; - - case DN_MOUSECLICK: - { - if (Param1 == LIST_BOX) - { - MOUSE_EVENT_RECORD *mer = (MOUSE_EVENT_RECORD *)Param2; - if (mer->dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED) - { - // find list on-screen coords (excluding frame and border) - SMALL_RECT list_rect; - Info.SendDlgMessage(hDlg, DM_GETDLGRECT, 0, reinterpret_cast(&list_rect)); - list_rect.Left += 2; - list_rect.Top += 1; - list_rect.Right -= 2; - list_rect.Bottom -= 1; - if ((mer->dwEventFlags == 0) && (mer->dwMousePosition.X > list_rect.Left) && (mer->dwMousePosition.X < list_rect.Right) && (mer->dwMousePosition.Y > list_rect.Top) && (mer->dwMousePosition.Y < list_rect.Bottom)) - { - DlgProc(hDlg, DN_KEY, LIST_BOX, KEY_ENTER); - return TRUE; - } - // pass message to scrollbar if needed - if ((mer->dwMousePosition.X == list_rect.Right) && (mer->dwMousePosition.Y > list_rect.Top) && (mer->dwMousePosition.Y < list_rect.Bottom)) return FALSE; - return TRUE; - } - else if (mer->dwButtonState == RIGHTMOST_BUTTON_PRESSED) - { - Info.SendDlgMessage(hDlg,DMU_UPDATE,0,2); - return TRUE; - } - } - } - break; - - case DN_KEY: - switch (Param2) - { - case KEY_F8: - { - if (ListSize) - { - TCHAR DlgText[MAX_PATH + 200]; - StringCchPrintf(DlgText, ARRAYSIZE(DlgText), GetMsg(MConfirm), p[Info.SendDlgMessage(hDlg,DM_LISTGETCURPOS,LIST_BOX,NULL)].Keys[DisplayName]); - if (EMessage((const TCHAR * const *) DlgText, 0, 2) == 0) - { - if (!DeleteEntry(static_cast(Info.SendDlgMessage(hDlg,DM_LISTGETCURPOS,LIST_BOX,NULL)))) - DrawMessage(FMSG_WARNING, 1, "%s",GetMsg(MPlugIn),GetMsg(MDelRegErr),GetMsg(MBtnOk),NULL); - Info.SendDlgMessage(hDlg,DMU_UPDATE,1,0); - } - } - } - return TRUE; - - case (KEY_F9|KEY_SHIFT|KEY_ALT): - case (KEY_F9): - { - Configure(0); - } - return TRUE; - - case KEY_CTRLR: - { - Info.SendDlgMessage(hDlg,DMU_UPDATE,1,0); - } - return TRUE; - - case KEY_INS: - { - Info.SendDlgMessage(hDlg,DMU_UPDATE,0,1); - } - return TRUE; - - case KEY_ENTER: - case KEY_SHIFTENTER: - { - if (ListSize) - { - int liChanged = 0; - int liSelected = 0, liFirst = -1; - - for (int i = 0; i < nCount; i++) - { - if (FLI[i].Flags & LIF_CHECKED) - { - if (liFirst == -1) - liFirst = i; - liSelected++; - } - } - - if (liSelected <= 1) - { - int liAction = (Param2 == KEY_ENTER) ? Opt.EnterAction : Opt.ShiftEnterAction; - int pos = (liFirst == -1) ? static_cast(Info.SendDlgMessage(hDlg,DM_LISTGETCURPOS,LIST_BOX,NULL)) : liFirst; - liChanged = ExecuteEntry(pos, liAction, (Opt.RunLowPriority!=0)); - } - else - { - int liAction = (Param2 == KEY_ENTER) ? Opt.EnterAction : Opt.ShiftEnterAction; - bool LowPriority = (Opt.RunLowPriority!=0); - - // Обязательно ожидание - два инсталлятора сразу недопускаются - if (liAction == Action_Menu) - { - if (EntryMenu(0, liAction, LowPriority, liSelected) < 0) - return TRUE; - } - else if (liAction == Action_Uninstall) - liAction = Action_UninstallWait; - else if (liAction == Action_Modify) - liAction = Action_ModifyWait; - else if (liAction == Action_Repair) - liAction = Action_RepairWait; - - for (int pos = 0; pos < nCount; pos++) - { - if (!(FLI[pos].Flags & LIF_CHECKED)) - continue; - struct FarListPos FLP; - FLP.SelectPos = pos; - FLP.TopPos = -1; - Info.SendDlgMessage(hDlg,DM_LISTSETCURPOS,LIST_BOX,reinterpret_cast(&FLP)); - int li = ExecuteEntry(pos, liAction, LowPriority); - if (li == -1) - break; // отмена - if (li == 1) - liChanged = 1; - } - } - - if (liChanged == 1) - { - Info.SendDlgMessage(hDlg,DMU_UPDATE,1,0); - } - } - } - return TRUE; - - case KEY_SHIFTINS: - case KEY_CTRLV: - { - TCHAR * bufP = FSF.PasteFromClipboard(); - static TCHAR bufData[MAX_PATH]; - if (bufP) - { - StringCchCopy(bufData,ARRAYSIZE(bufData),bufP); - FSF.DeleteBuffer(bufP); - unQuote(bufData); - FSF.LStrlwr(bufData); - for (int i = lstrlen(bufData); i >= 1; i--) - for (int j = 0; j < nCount; j++) - if (strnstri(p[j].Keys[DisplayName],bufData,i)) - { - lstrcpyn(Filter,bufData,i+1); - Info.SendDlgMessage(hDlg,DMU_UPDATE,0,0); - return TRUE; - } - } - } - return TRUE; - - case KEY_DEL: - { - if (lstrlen(Filter) > 0) - { - StringCchCopy(Filter,ARRAYSIZE(Filter),_T("")); - Info.SendDlgMessage(hDlg,DMU_UPDATE,0,0); - } - } - return TRUE; - - case KEY_F3: - case KEY_F4: - { - if (ListSize) - { - DisplayEntry(static_cast(Info.SendDlgMessage(hDlg,DM_LISTGETCURPOS,LIST_BOX,NULL))); - Info.SendDlgMessage(hDlg,DM_REDRAW,NULL,NULL); - } - } - return TRUE; - - case KEY_F2: - { - Opt.SortByDate = !Opt.SortByDate; - Info.SendDlgMessage(hDlg,DMU_UPDATE,1,0); - } - return TRUE; - - case KEY_BS: - { - if (lstrlen(Filter)) - { - Filter[lstrlen(Filter)-1] = '\0'; - Info.SendDlgMessage(hDlg,DMU_UPDATE,0,0); - } - } - return TRUE; - - default: - { - if (Param2 >= KEY_SPACE && Param2 < KEY_FKEY_BEGIN) - { - struct FarListInfo ListInfo; - Info.SendDlgMessage(hDlg,DM_LISTINFO,LIST_BOX,reinterpret_cast(&ListInfo)); - if ((lstrlen(Filter) < sizeof(Filter)) && ListInfo.ItemsNumber) - { - int filterL = lstrlen(Filter); - Filter[filterL] = FSF.LLower(static_cast(Param2)); - Filter[filterL+1] = '\0'; - Info.SendDlgMessage(hDlg,DMU_UPDATE,0,0); - return TRUE; - } - } - } - } - return FALSE; - - case DN_CTLCOLORDIALOG: - return Info.AdvControl(Info.ModuleNumber,ACTL_GETCOLOR,(void *)COL_MENUTEXT); - - case DN_CTLCOLORDLGLIST: - if (Param1 == LIST_BOX) - { - FarListColors *Colors = (FarListColors *)Param2; - int ColorIndex[] = { COL_MENUBOX, COL_MENUBOX, COL_MENUTITLE, COL_MENUTEXT, COL_MENUHIGHLIGHT, COL_MENUBOX, COL_MENUSELECTEDTEXT, COL_MENUSELECTEDHIGHLIGHT, COL_MENUSCROLLBAR, COL_MENUDISABLEDTEXT, COL_MENUARROWS, COL_MENUARROWSSELECTED, COL_MENUARROWSDISABLED }; - int Count = ARRAYSIZE(ColorIndex); - if (Count > Colors->ColorCount) - Count = Colors->ColorCount; - for (int i = 0; i < Count; i++) - Colors->Colors[i] = static_cast(Info.AdvControl(Info.ModuleNumber, ACTL_GETCOLOR, reinterpret_cast(ColorIndex[i]))); - return TRUE; - } - break; - } - return Info.DefDlgProc(hDlg,Msg,Param1,Param2); + static TCHAR Filter[MAX_PATH]; + static TCHAR spFilter[MAX_PATH]; + static FarListTitles ListTitle; + + switch(Msg) + { + case DN_RESIZECONSOLE: + { + Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,FALSE,0); + ResizeDialog(hDlg); + Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,TRUE,0); + } + return TRUE; + case DMU_UPDATE: + { + int OldPos = static_cast(Info.SendDlgMessage(hDlg,DM_LISTGETCURPOS,LIST_BOX,0)); + + if(Param1) + UpDateInfo(); + + ListSize = 0; + int NewPos = -1; + + if(OldPos >= 0 && OldPos < nCount) + { + if(!*Filter || strstri(p[OldPos].Keys[DisplayName],Filter)) //без учета регистра в OEM кодировке + NewPos = OldPos; + } + + for(int i = 0; i < nCount; i++) + { + const TCHAR* DispName = p[i].Keys[DisplayName], *Find; + + if(*Filter) + Find = strstri(DispName,Filter); + else + Find = DispName; + + if(Find != nullptr) //без учета регистра в OEM кодировке + { + FLI[i].Flags &= ~LIF_HIDDEN; + + if(Param2 && (i == OldPos)) + { + if(FLI[i].Flags & LIF_CHECKED) + { + FLI[i].Flags &= ~LIF_CHECKED; + } + else + { + FLI[i].Flags |= LIF_CHECKED; + } + } + + //без учета регистра - а кодировка ANSI + if(NewPos == -1 && Find == DispName) + NewPos = i; + + ListSize++; + } + else + FLI[i].Flags |= LIF_HIDDEN; + } + + if(Param1 == 0 && Param2) + { + // Снятие или установка пометки (Ins) + if(Param2 == 1) + { + for(int i = (OldPos+1); i < nCount; i++) + { + if(!(FLI[i].Flags & LIF_HIDDEN)) + { + OldPos = i; break; + } + } + + NewPos = OldPos; + } + // Снятие или установка пометки (RClick) + else if(Param2 == 2) + { + NewPos = OldPos; + } + } + else if(NewPos == -1) + { + NewPos = OldPos; + } + + Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,FALSE,0); + Info.SendDlgMessage(hDlg,DM_LISTSET,LIST_BOX,reinterpret_cast(&FL)); + StringCchPrintf(spFilter,ARRAYSIZE(spFilter), GetMsg(MFilter),Filter,ListSize,nCount); + ListTitle.Title = spFilter; + ListTitle.TitleLen = lstrlen(spFilter); + Info.SendDlgMessage(hDlg,DM_LISTSETTITLES,LIST_BOX,reinterpret_cast(&ListTitle)); + ResizeDialog(hDlg); + struct FarListPos FLP; + FLP.SelectPos = NewPos; + FLP.TopPos = -1; + Info.SendDlgMessage(hDlg,DM_LISTSETCURPOS,LIST_BOX,reinterpret_cast(&FLP)); + Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,TRUE,0); + } + break; + case DN_INITDIALOG: + { + StringCchCopy(Filter,ARRAYSIZE(Filter),_T("")); + ListTitle.Bottom = const_cast(GetMsg(MBottomLine)); + ListTitle.BottomLen = lstrlen(GetMsg(MBottomLine)); + //подстраиваемся под размеры консоли + Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,FALSE,0); + ResizeDialog(hDlg); + Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,TRUE,0); + //заполняем диалог + Info.SendDlgMessage(hDlg,DMU_UPDATE,1,0); + } + break; + case DN_MOUSECLICK: + { + if(Param1 == LIST_BOX) + { + MOUSE_EVENT_RECORD *mer = (MOUSE_EVENT_RECORD *)Param2; + + if(mer->dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED) + { + // find list on-screen coords (excluding frame and border) + SMALL_RECT list_rect; + Info.SendDlgMessage(hDlg, DM_GETDLGRECT, 0, reinterpret_cast(&list_rect)); + list_rect.Left += 2; + list_rect.Top += 1; + list_rect.Right -= 2; + list_rect.Bottom -= 1; + + if((mer->dwEventFlags == 0) && (mer->dwMousePosition.X > list_rect.Left) && (mer->dwMousePosition.X < list_rect.Right) && (mer->dwMousePosition.Y > list_rect.Top) && (mer->dwMousePosition.Y < list_rect.Bottom)) + { + DlgProc(hDlg, DN_KEY, LIST_BOX, KEY_ENTER); + return TRUE; + } + + // pass message to scrollbar if needed + if((mer->dwMousePosition.X == list_rect.Right) && (mer->dwMousePosition.Y > list_rect.Top) && (mer->dwMousePosition.Y < list_rect.Bottom)) return FALSE; + + return TRUE; + } + else if(mer->dwButtonState == RIGHTMOST_BUTTON_PRESSED) + { + Info.SendDlgMessage(hDlg,DMU_UPDATE,0,2); + return TRUE; + } + } + } + break; + case DN_KEY: + + switch(Param2) + { + case KEY_F8: + { + if(ListSize) + { + TCHAR DlgText[MAX_PATH + 200]; + StringCchPrintf(DlgText, ARRAYSIZE(DlgText), GetMsg(MConfirm), p[Info.SendDlgMessage(hDlg,DM_LISTGETCURPOS,LIST_BOX,NULL)].Keys[DisplayName]); + + if(EMessage((const TCHAR * const *) DlgText, 0, 2) == 0) + { + if(!DeleteEntry(static_cast(Info.SendDlgMessage(hDlg,DM_LISTGETCURPOS,LIST_BOX,NULL)))) + DrawMessage(FMSG_WARNING, 1, "%s",GetMsg(MPlugIn),GetMsg(MDelRegErr),GetMsg(MBtnOk),NULL); + + Info.SendDlgMessage(hDlg,DMU_UPDATE,1,0); + } + } + } + return TRUE; + case(KEY_F9|KEY_SHIFT|KEY_ALT): + case(KEY_F9): + { + Configure(0); + } + return TRUE; + case KEY_CTRLR: + { + Info.SendDlgMessage(hDlg,DMU_UPDATE,1,0); + } + return TRUE; + case KEY_INS: + { + Info.SendDlgMessage(hDlg,DMU_UPDATE,0,1); + } + return TRUE; + case KEY_ENTER: + case KEY_SHIFTENTER: + { + if(ListSize) + { + int liChanged = 0; + int liSelected = 0, liFirst = -1; + + for(int i = 0; i < nCount; i++) + { + if(FLI[i].Flags & LIF_CHECKED) + { + if(liFirst == -1) + liFirst = i; + + liSelected++; + } + } + + if(liSelected <= 1) + { + int liAction = (Param2 == KEY_ENTER) ? Opt.EnterAction : Opt.ShiftEnterAction; + int pos = (liFirst == -1) ? static_cast(Info.SendDlgMessage(hDlg,DM_LISTGETCURPOS,LIST_BOX,NULL)) : liFirst; + liChanged = ExecuteEntry(pos, liAction, (Opt.RunLowPriority!=0)); + } + else + { + int liAction = (Param2 == KEY_ENTER) ? Opt.EnterAction : Opt.ShiftEnterAction; + bool LowPriority = (Opt.RunLowPriority!=0); + + // Обязательно ожидание - два инсталлятора сразу недопускаются + if(liAction == Action_Menu) + { + if(EntryMenu(0, liAction, LowPriority, liSelected) < 0) + return TRUE; + } + else if(liAction == Action_Uninstall) + liAction = Action_UninstallWait; + else if(liAction == Action_Modify) + liAction = Action_ModifyWait; + else if(liAction == Action_Repair) + liAction = Action_RepairWait; + + for(int pos = 0; pos < nCount; pos++) + { + if(!(FLI[pos].Flags & LIF_CHECKED)) + continue; + + struct FarListPos FLP; + FLP.SelectPos = pos; + FLP.TopPos = -1; + Info.SendDlgMessage(hDlg,DM_LISTSETCURPOS,LIST_BOX,reinterpret_cast(&FLP)); + int li = ExecuteEntry(pos, liAction, LowPriority); + + if(li == -1) + break; // отмена + + if(li == 1) + liChanged = 1; + } + } + + if(liChanged == 1) + { + Info.SendDlgMessage(hDlg,DMU_UPDATE,1,0); + } + } + } + return TRUE; + case KEY_SHIFTINS: + case KEY_CTRLV: + { + TCHAR * bufP = FSF.PasteFromClipboard(); + static TCHAR bufData[MAX_PATH]; + + if(bufP) + { + StringCchCopy(bufData,ARRAYSIZE(bufData),bufP); + FSF.DeleteBuffer(bufP); + unQuote(bufData); + FSF.LStrlwr(bufData); + + for(int i = lstrlen(bufData); i >= 1; i--) + for(int j = 0; j < nCount; j++) + if(strnstri(p[j].Keys[DisplayName],bufData,i)) + { + lstrcpyn(Filter,bufData,i+1); + Info.SendDlgMessage(hDlg,DMU_UPDATE,0,0); + return TRUE; + } + } + } + return TRUE; + case KEY_DEL: + { + if(lstrlen(Filter) > 0) + { + StringCchCopy(Filter,ARRAYSIZE(Filter),_T("")); + Info.SendDlgMessage(hDlg,DMU_UPDATE,0,0); + } + } + return TRUE; + case KEY_F3: + case KEY_F4: + { + if(ListSize) + { + DisplayEntry(static_cast(Info.SendDlgMessage(hDlg,DM_LISTGETCURPOS,LIST_BOX,NULL))); + Info.SendDlgMessage(hDlg,DM_REDRAW,NULL,NULL); + } + } + return TRUE; + case KEY_F2: + { + Opt.SortByDate = !Opt.SortByDate; + Info.SendDlgMessage(hDlg,DMU_UPDATE,1,0); + } + return TRUE; + case KEY_BS: + { + if(lstrlen(Filter)) + { + Filter[lstrlen(Filter)-1] = '\0'; + Info.SendDlgMessage(hDlg,DMU_UPDATE,0,0); + } + } + return TRUE; + default: + { + if(Param2 >= KEY_SPACE && Param2 < KEY_FKEY_BEGIN) + { + struct FarListInfo ListInfo; + Info.SendDlgMessage(hDlg,DM_LISTINFO,LIST_BOX,reinterpret_cast(&ListInfo)); + + if((lstrlen(Filter) < sizeof(Filter)) && ListInfo.ItemsNumber) + { + int filterL = lstrlen(Filter); + Filter[filterL] = FSF.LLower(static_cast(Param2)); + Filter[filterL+1] = '\0'; + Info.SendDlgMessage(hDlg,DMU_UPDATE,0,0); + return TRUE; + } + } + } + } + + return FALSE; + case DN_CTLCOLORDIALOG: + return Info.AdvControl(Info.ModuleNumber,ACTL_GETCOLOR,(void *)COL_MENUTEXT); + case DN_CTLCOLORDLGLIST: + + if(Param1 == LIST_BOX) + { + FarListColors *Colors = (FarListColors *)Param2; + int ColorIndex[] = { COL_MENUBOX, COL_MENUBOX, COL_MENUTITLE, COL_MENUTEXT, COL_MENUHIGHLIGHT, COL_MENUBOX, COL_MENUSELECTEDTEXT, COL_MENUSELECTEDHIGHLIGHT, COL_MENUSCROLLBAR, COL_MENUDISABLEDTEXT, COL_MENUARROWS, COL_MENUARROWSSELECTED, COL_MENUARROWSDISABLED }; + int Count = ARRAYSIZE(ColorIndex); + + if(Count > Colors->ColorCount) + Count = Colors->ColorCount; + + for(int i = 0; i < Count; i++) + Colors->Colors[i] = static_cast(Info.AdvControl(Info.ModuleNumber, ACTL_GETCOLOR, reinterpret_cast(ColorIndex[i]))); + + return TRUE; + } + + break; + } + + return Info.DefDlgProc(hDlg,Msg,Param1,Param2); } HANDLE WINAPI OpenPlugin(int /*OpenFrom*/, INT_PTR /*Item*/) { - ReadRegistry(); - struct FarDialogItem DialogItems[1]; - ZeroMemory(DialogItems, sizeof(DialogItems)); - p = NULL; - FLI = NULL; - - hStdout = GetStdHandle(STD_OUTPUT_HANDLE); - UpDateInfo(); - - DialogItems[0].Type = DI_LISTBOX; - DialogItems[0].Flags = DIF_LISTNOAMPERSAND; - DialogItems[0].X1 = 2; - DialogItems[0].Y1 = 1; - + ReadRegistry(); + struct FarDialogItem DialogItems[1]; + ZeroMemory(DialogItems, sizeof(DialogItems)); + p = NULL; + FLI = NULL; + hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + UpDateInfo(); + DialogItems[0].Type = DI_LISTBOX; + DialogItems[0].Flags = DIF_LISTNOAMPERSAND; + DialogItems[0].X1 = 2; + DialogItems[0].Y1 = 1; #ifdef FARAPI17 - Info.DialogEx(Info.ModuleNumber,-1,-1,0,0,"Contents",DialogItems,ARRAYSIZE(DialogItems),0,0,DlgProc,0); + Info.DialogEx(Info.ModuleNumber,-1,-1,0,0,"Contents",DialogItems,ARRAYSIZE(DialogItems),0,0,DlgProc,0); #endif #ifdef FARAPI18 - HANDLE h_dlg = Info.DialogInit(Info.ModuleNumber,-1,-1,0,0,L"Contents",DialogItems,ARRAYSIZE(DialogItems),0,0,DlgProc,0); - if (h_dlg != INVALID_HANDLE_VALUE) { - Info.DialogRun(h_dlg); - Info.DialogFree(h_dlg); - } + HANDLE h_dlg = Info.DialogInit(Info.ModuleNumber,-1,-1,0,0,L"Contents",DialogItems,ARRAYSIZE(DialogItems),0,0,DlgProc,0); + + if(h_dlg != INVALID_HANDLE_VALUE) + { + Info.DialogRun(h_dlg); + Info.DialogFree(h_dlg); + } + #endif - FLI = (FarListItem *) realloc(FLI, 0); - p = (KeyInfo *) realloc(p, 0); - return INVALID_HANDLE_VALUE; + FLI = (FarListItem *) realloc(FLI, 0); + p = (KeyInfo *) realloc(p, 0); + return INVALID_HANDLE_VALUE; } int WINAPI Configure(int ItemNumber) { - PluginDialogBuilder Config(Info, MPlugIn, _T("Configuration")); - FarDialogItem *p1, *p2; - - BOOL bShowInViewer = (Opt.WhereWork & 1) != 0; - BOOL bShowInEditor = (Opt.WhereWork & 2) != 0; - //BOOL bEnterWaitCompletion = (Opt.EnterFunction != 0); - BOOL bUseElevation = (Opt.UseElevation != 0); - BOOL bLowPriority = (Opt.RunLowPriority != 0); - BOOL bForceMsiUse = (Opt.ForceMsiUse != 0); - - Config.AddCheckbox(MShowInEditor, &bShowInEditor); - Config.AddCheckbox(MShowInViewer, &bShowInViewer); - //Config.AddCheckbox(MEnterWaitCompletion, &bEnterWaitCompletion); - Config.AddCheckbox(MUseElevation, &bUseElevation); - Config.AddCheckbox(MLowPriority, &bUseElevation); - Config.AddCheckbox(MForceMsiUse, &bForceMsiUse); - - Config.AddSeparator(); - - FarList AEnter, AShiftEnter; - AEnter.ItemsNumber = AShiftEnter.ItemsNumber = 7; - AEnter.Items = (FarListItem*)calloc(AEnter.ItemsNumber,sizeof(FarListItem)); - AShiftEnter.Items = (FarListItem*)calloc(AEnter.ItemsNumber,sizeof(FarListItem)); - for (int i = 0; i < AEnter.ItemsNumber; i++) - { - #ifdef FARAPI18 - AEnter.Items[i].Text = GetMsg(MActionUninstallWait+i); - AShiftEnter.Items[i].Text = AEnter.Items[i].Text; - #else - StringCchCopy(AEnter.Items[i].Text,ARRAYSIZE(AEnter.Items[i].Text),GetMsg(MActionUninstallWait+i)); - StringCchCopy(AShiftEnter.Items[i].Text,ARRAYSIZE(AShiftEnter.Items[i].Text),AEnter.Items[i].Text); - #endif - } - - p1 = Config.AddText(MEnterAction); p2 = Config.AddComboBox(23, &AEnter, &Opt.EnterAction); - Config.MoveItemAfter(p1,p2); - p1 = Config.AddText(MShiftEnterAction); p2 = Config.AddComboBox(23, &AShiftEnter, &Opt.ShiftEnterAction); - Config.MoveItemAfter(p1,p2); - - - - Config.AddOKCancel(MBtnOk, MBtnCancel); - - if (Config.ShowDialog()) - { - Opt.WhereWork = (bShowInViewer ? 1 : 0) | (bShowInEditor ? 2 : 0); - //Opt.EnterFunction = bEnterWaitCompletion; - Opt.UseElevation = bUseElevation; - Opt.RunLowPriority = bLowPriority; - Opt.ForceMsiUse = bForceMsiUse; - - SetRegKey(HKCU,_T(""),_T("WhereWork"),(DWORD) Opt.WhereWork); - SetRegKey(HKCU,_T(""),_T("EnterAction"),(DWORD) Opt.EnterAction); - SetRegKey(HKCU,_T(""),_T("ShiftEnterAction"),(DWORD) Opt.ShiftEnterAction); - SetRegKey(HKCU,_T(""),_T("UseElevation"),(DWORD) Opt.UseElevation); - SetRegKey(HKCU,_T(""),_T("RunLowPriority"),(DWORD) Opt.RunLowPriority); - SetRegKey(HKCU,_T(""),_T("ForceMsiUse"),(DWORD) Opt.ForceMsiUse); - } - - return FALSE; + PluginDialogBuilder Config(Info, MPlugIn, _T("Configuration")); + FarDialogItem *p1, *p2; + BOOL bShowInViewer = (Opt.WhereWork & 1) != 0; + BOOL bShowInEditor = (Opt.WhereWork & 2) != 0; + //BOOL bEnterWaitCompletion = (Opt.EnterFunction != 0); + BOOL bUseElevation = (Opt.UseElevation != 0); + BOOL bLowPriority = (Opt.RunLowPriority != 0); + BOOL bForceMsiUse = (Opt.ForceMsiUse != 0); + Config.AddCheckbox(MShowInEditor, &bShowInEditor); + Config.AddCheckbox(MShowInViewer, &bShowInViewer); + //Config.AddCheckbox(MEnterWaitCompletion, &bEnterWaitCompletion); + Config.AddCheckbox(MUseElevation, &bUseElevation); + Config.AddCheckbox(MLowPriority, &bUseElevation); + Config.AddCheckbox(MForceMsiUse, &bForceMsiUse); + Config.AddSeparator(); + FarList AEnter, AShiftEnter; + AEnter.ItemsNumber = AShiftEnter.ItemsNumber = 7; + AEnter.Items = (FarListItem*)calloc(AEnter.ItemsNumber,sizeof(FarListItem)); + AShiftEnter.Items = (FarListItem*)calloc(AEnter.ItemsNumber,sizeof(FarListItem)); + + for(int i = 0; i < AEnter.ItemsNumber; i++) + { +#ifdef FARAPI18 + AEnter.Items[i].Text = GetMsg(MActionUninstallWait+i); + AShiftEnter.Items[i].Text = AEnter.Items[i].Text; +#else + StringCchCopy(AEnter.Items[i].Text,ARRAYSIZE(AEnter.Items[i].Text),GetMsg(MActionUninstallWait+i)); + StringCchCopy(AShiftEnter.Items[i].Text,ARRAYSIZE(AShiftEnter.Items[i].Text),AEnter.Items[i].Text); +#endif + } + + p1 = Config.AddText(MEnterAction); p2 = Config.AddComboBox(23, &AEnter, &Opt.EnterAction); + Config.MoveItemAfter(p1,p2); + p1 = Config.AddText(MShiftEnterAction); p2 = Config.AddComboBox(23, &AShiftEnter, &Opt.ShiftEnterAction); + Config.MoveItemAfter(p1,p2); + Config.AddOKCancel(MBtnOk, MBtnCancel); + + if(Config.ShowDialog()) + { + Opt.WhereWork = (bShowInViewer ? 1 : 0) | (bShowInEditor ? 2 : 0); + //Opt.EnterFunction = bEnterWaitCompletion; + Opt.UseElevation = bUseElevation; + Opt.RunLowPriority = bLowPriority; + Opt.ForceMsiUse = bForceMsiUse; + SetRegKey(HKCU,_T(""),_T("WhereWork"),(DWORD) Opt.WhereWork); + SetRegKey(HKCU,_T(""),_T("EnterAction"),(DWORD) Opt.EnterAction); + SetRegKey(HKCU,_T(""),_T("ShiftEnterAction"),(DWORD) Opt.ShiftEnterAction); + SetRegKey(HKCU,_T(""),_T("UseElevation"),(DWORD) Opt.UseElevation); + SetRegKey(HKCU,_T(""),_T("RunLowPriority"),(DWORD) Opt.RunLowPriority); + SetRegKey(HKCU,_T(""),_T("ForceMsiUse"),(DWORD) Opt.ForceMsiUse); + } + + return FALSE; } diff --git a/Uninstall/src/UnInstall.cpp.orig b/Uninstall/src/UnInstall.cpp.orig new file mode 100644 index 0000000..2332920 --- /dev/null +++ b/Uninstall/src/UnInstall.cpp.orig @@ -0,0 +1,542 @@ +#include +#include +#include +#include +#include +#include "plugin.hpp" +#include "memory.h" +#define realloc my_realloc +#ifndef nullptr + #define nullptr NULL +#endif +#ifndef _ASSERTE + #define _ASSERTE(x) +#endif +#include "DlgBuilder.hpp" +#include "eplugin.cpp" +#include "farcolor.hpp" +#include "farkeys.hpp" +#include "farlang.h" +#include "registry.cpp" +#include "uninstall.hpp" + +#ifdef FARAPI18 +# define SetStartupInfo SetStartupInfoW +# define GetPluginInfo GetPluginInfoW +# define OpenPlugin OpenPluginW +# define Configure ConfigureW +#endif + +#ifdef FARAPI17 +int WINAPI GetMinFarVersion(void) +{ + return MAKEFARVERSION(1,75,2555); +} +#endif +#ifdef FARAPI18 +int WINAPI GetMinFarVersion(void) +{ + return FARMANAGERVERSION; +} +int WINAPI GetMinFarVersionW(void) +{ + return FARMANAGERVERSION; +} +#endif + +void WINAPI SetStartupInfo(const struct PluginStartupInfo *psInfo) +{ + Info = *psInfo; + FSF = *psInfo->FSF; + Info.FSF = &FSF; + InitHeap(); + StringCchCopy(PluginRootKey,ARRAYSIZE(PluginRootKey),Info.RootKey); + StringCchCat(PluginRootKey,ARRAYSIZE(PluginRootKey),_T("\\UnInstall")); + ReadRegistry(); +} + +void WINAPI GetPluginInfo(struct PluginInfo *Info) +{ + static const TCHAR *PluginMenuStrings[1]; + PluginMenuStrings[0] = GetMsg(MPlugIn); + Info -> StructSize = sizeof(*Info); + Info -> PluginMenuStrings = PluginMenuStrings; + Info -> PluginConfigStrings = PluginMenuStrings; + if (Opt.WhereWork & 2) + Info -> Flags |= PF_EDITOR; + if (Opt.WhereWork & 1) + Info -> Flags |= PF_VIEWER; + Info -> PluginMenuStringsNumber = ARRAYSIZE(PluginMenuStrings); + Info -> PluginConfigStringsNumber = ARRAYSIZE(PluginMenuStrings); +} + +void ResizeDialog(HANDLE hDlg) { + CONSOLE_SCREEN_BUFFER_INFO con_info; + GetConsoleScreenBufferInfo(hStdout, &con_info); + unsigned con_sx = con_info.srWindow.Right - con_info.srWindow.Left + 1; + int max_items = con_info.srWindow.Bottom - con_info.srWindow.Top + 1 - 7; + int s = ((ListSize>0) && (ListSize0 ? max_items : 0)); + SMALL_RECT NewPos = { 2, 1, con_sx - 7, s + 2 }; + SMALL_RECT OldPos; + Info.SendDlgMessage(hDlg,DM_GETITEMPOSITION,LIST_BOX,reinterpret_cast(&OldPos)); + if (NewPos.Right!=OldPos.Right || NewPos.Bottom!=OldPos.Bottom) { + COORD coord; + coord.X = con_sx - 4; + coord.Y = s + 4; + Info.SendDlgMessage(hDlg,DM_RESIZEDIALOG,0,reinterpret_cast(&coord)); + coord.X = -1; + coord.Y = -1; + Info.SendDlgMessage(hDlg,DM_MOVEDIALOG,TRUE,reinterpret_cast(&coord)); + Info.SendDlgMessage(hDlg,DM_SETITEMPOSITION,LIST_BOX,reinterpret_cast(&NewPos)); + } +} + +static LONG_PTR WINAPI DlgProc(HANDLE hDlg,int Msg,int Param1,LONG_PTR Param2) +{ + static TCHAR Filter[MAX_PATH]; + static TCHAR spFilter[MAX_PATH]; + static FarListTitles ListTitle; + + switch(Msg) + { + case DN_RESIZECONSOLE: + { + Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,FALSE,0); + ResizeDialog(hDlg); + Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,TRUE,0); + } + return TRUE; + + case DMU_UPDATE: + { + int OldPos = static_cast(Info.SendDlgMessage(hDlg,DM_LISTGETCURPOS,LIST_BOX,0)); + + if (Param1) + UpDateInfo(); + + ListSize = 0; + int NewPos = -1; + if (OldPos >= 0 && OldPos < nCount) + { + if (!*Filter || strstri(p[OldPos].Keys[DisplayName],Filter)) //без учета регистра в OEM кодировке + NewPos = OldPos; + } + for (int i = 0; i < nCount; i++) + { + const TCHAR* DispName = p[i].Keys[DisplayName], *Find; + if (*Filter) + Find = strstri(DispName,Filter); + else + Find = DispName; + if (Find != nullptr) //без учета регистра в OEM кодировке + { + FLI[i].Flags &= ~LIF_HIDDEN; + if (Param2 && (i == OldPos)) + { + if (FLI[i].Flags & LIF_CHECKED) + { + FLI[i].Flags &= ~LIF_CHECKED; + } + else + { + FLI[i].Flags |= LIF_CHECKED; + } + } + //без учета регистра - а кодировка ANSI + if (NewPos == -1 && Find == DispName) + NewPos = i; + ListSize++; + } + else + FLI[i].Flags |= LIF_HIDDEN; + } + if (Param1 == 0 && Param2) + { + // Снятие или установка пометки (Ins) + if (Param2 == 1) + { + for (int i = (OldPos+1); i < nCount; i++) + { + if (!(FLI[i].Flags & LIF_HIDDEN)) + { + OldPos = i; break; + } + } + NewPos = OldPos; + } + // Снятие или установка пометки (RClick) + else if (Param2 == 2) + { + NewPos = OldPos; + } + } + else if (NewPos == -1) + { + NewPos = OldPos; + } + + Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,FALSE,0); + + Info.SendDlgMessage(hDlg,DM_LISTSET,LIST_BOX,reinterpret_cast(&FL)); + + StringCchPrintf(spFilter,ARRAYSIZE(spFilter), GetMsg(MFilter),Filter,ListSize,nCount); + ListTitle.Title = spFilter; + ListTitle.TitleLen = lstrlen(spFilter); + Info.SendDlgMessage(hDlg,DM_LISTSETTITLES,LIST_BOX,reinterpret_cast(&ListTitle)); + + ResizeDialog(hDlg); + + struct FarListPos FLP; + FLP.SelectPos = NewPos; + FLP.TopPos = -1; + Info.SendDlgMessage(hDlg,DM_LISTSETCURPOS,LIST_BOX,reinterpret_cast(&FLP)); + + Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,TRUE,0); + } + break; + + case DN_INITDIALOG: + { + StringCchCopy(Filter,ARRAYSIZE(Filter),_T("")); + ListTitle.Bottom = const_cast(GetMsg(MBottomLine)); + ListTitle.BottomLen = lstrlen(GetMsg(MBottomLine)); + + //подстраиваемся под размеры консоли + Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,FALSE,0); + ResizeDialog(hDlg); + Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,TRUE,0); + //заполняем диалог + Info.SendDlgMessage(hDlg,DMU_UPDATE,1,0); + } + break; + + case DN_MOUSECLICK: + { + if (Param1 == LIST_BOX) + { + MOUSE_EVENT_RECORD *mer = (MOUSE_EVENT_RECORD *)Param2; + if (mer->dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED) + { + // find list on-screen coords (excluding frame and border) + SMALL_RECT list_rect; + Info.SendDlgMessage(hDlg, DM_GETDLGRECT, 0, reinterpret_cast(&list_rect)); + list_rect.Left += 2; + list_rect.Top += 1; + list_rect.Right -= 2; + list_rect.Bottom -= 1; + if ((mer->dwEventFlags == 0) && (mer->dwMousePosition.X > list_rect.Left) && (mer->dwMousePosition.X < list_rect.Right) && (mer->dwMousePosition.Y > list_rect.Top) && (mer->dwMousePosition.Y < list_rect.Bottom)) + { + DlgProc(hDlg, DN_KEY, LIST_BOX, KEY_ENTER); + return TRUE; + } + // pass message to scrollbar if needed + if ((mer->dwMousePosition.X == list_rect.Right) && (mer->dwMousePosition.Y > list_rect.Top) && (mer->dwMousePosition.Y < list_rect.Bottom)) return FALSE; + return TRUE; + } + else if (mer->dwButtonState == RIGHTMOST_BUTTON_PRESSED) + { + Info.SendDlgMessage(hDlg,DMU_UPDATE,0,2); + return TRUE; + } + } + } + break; + + case DN_KEY: + switch (Param2) + { + case KEY_F8: + { + if (ListSize) + { + TCHAR DlgText[MAX_PATH + 200]; + StringCchPrintf(DlgText, ARRAYSIZE(DlgText), GetMsg(MConfirm), p[Info.SendDlgMessage(hDlg,DM_LISTGETCURPOS,LIST_BOX,NULL)].Keys[DisplayName]); + if (EMessage((const TCHAR * const *) DlgText, 0, 2) == 0) + { + if (!DeleteEntry(static_cast(Info.SendDlgMessage(hDlg,DM_LISTGETCURPOS,LIST_BOX,NULL)))) + DrawMessage(FMSG_WARNING, 1, "%s",GetMsg(MPlugIn),GetMsg(MDelRegErr),GetMsg(MBtnOk),NULL); + Info.SendDlgMessage(hDlg,DMU_UPDATE,1,0); + } + } + } + return TRUE; + + case (KEY_F9|KEY_SHIFT|KEY_ALT): + case (KEY_F9): + { + Configure(0); + } + return TRUE; + + case KEY_CTRLR: + { + Info.SendDlgMessage(hDlg,DMU_UPDATE,1,0); + } + return TRUE; + + case KEY_INS: + { + Info.SendDlgMessage(hDlg,DMU_UPDATE,0,1); + } + return TRUE; + + case KEY_ENTER: + case KEY_SHIFTENTER: + { + if (ListSize) + { + int liChanged = 0; + int liSelected = 0, liFirst = -1; + + for (int i = 0; i < nCount; i++) + { + if (FLI[i].Flags & LIF_CHECKED) + { + if (liFirst == -1) + liFirst = i; + liSelected++; + } + } + + if (liSelected <= 1) + { + int liAction = (Param2 == KEY_ENTER) ? Opt.EnterAction : Opt.ShiftEnterAction; + int pos = (liFirst == -1) ? static_cast(Info.SendDlgMessage(hDlg,DM_LISTGETCURPOS,LIST_BOX,NULL)) : liFirst; + liChanged = ExecuteEntry(pos, liAction, (Opt.RunLowPriority!=0)); + } + else + { + int liAction = (Param2 == KEY_ENTER) ? Opt.EnterAction : Opt.ShiftEnterAction; + bool LowPriority = (Opt.RunLowPriority!=0); + + // Обязательно ожидание - два инсталлятора сразу недопускаются + if (liAction == Action_Menu) + { + if (EntryMenu(0, liAction, LowPriority, liSelected) < 0) + return TRUE; + } + else if (liAction == Action_Uninstall) + liAction = Action_UninstallWait; + else if (liAction == Action_Modify) + liAction = Action_ModifyWait; + else if (liAction == Action_Repair) + liAction = Action_RepairWait; + + for (int pos = 0; pos < nCount; pos++) + { + if (!(FLI[pos].Flags & LIF_CHECKED)) + continue; + struct FarListPos FLP; + FLP.SelectPos = pos; + FLP.TopPos = -1; + Info.SendDlgMessage(hDlg,DM_LISTSETCURPOS,LIST_BOX,reinterpret_cast(&FLP)); + int li = ExecuteEntry(pos, liAction, LowPriority); + if (li == -1) + break; // отмена + if (li == 1) + liChanged = 1; + } + } + + if (liChanged == 1) + { + Info.SendDlgMessage(hDlg,DMU_UPDATE,1,0); + } + } + } + return TRUE; + + case KEY_SHIFTINS: + case KEY_CTRLV: + { + TCHAR * bufP = FSF.PasteFromClipboard(); + static TCHAR bufData[MAX_PATH]; + if (bufP) + { + StringCchCopy(bufData,ARRAYSIZE(bufData),bufP); + FSF.DeleteBuffer(bufP); + unQuote(bufData); + FSF.LStrlwr(bufData); + for (int i = lstrlen(bufData); i >= 1; i--) + for (int j = 0; j < nCount; j++) + if (strnstri(p[j].Keys[DisplayName],bufData,i)) + { + lstrcpyn(Filter,bufData,i+1); + Info.SendDlgMessage(hDlg,DMU_UPDATE,0,0); + return TRUE; + } + } + } + return TRUE; + + case KEY_DEL: + { + if (lstrlen(Filter) > 0) + { + StringCchCopy(Filter,ARRAYSIZE(Filter),_T("")); + Info.SendDlgMessage(hDlg,DMU_UPDATE,0,0); + } + } + return TRUE; + + case KEY_F3: + case KEY_F4: + { + if (ListSize) + { + DisplayEntry(static_cast(Info.SendDlgMessage(hDlg,DM_LISTGETCURPOS,LIST_BOX,NULL))); + Info.SendDlgMessage(hDlg,DM_REDRAW,NULL,NULL); + } + } + return TRUE; + + case KEY_F2: + { + Opt.SortByDate = !Opt.SortByDate; + Info.SendDlgMessage(hDlg,DMU_UPDATE,1,0); + } + return TRUE; + + case KEY_BS: + { + if (lstrlen(Filter)) + { + Filter[lstrlen(Filter)-1] = '\0'; + Info.SendDlgMessage(hDlg,DMU_UPDATE,0,0); + } + } + return TRUE; + + default: + { + if (Param2 >= KEY_SPACE && Param2 < KEY_FKEY_BEGIN) + { + struct FarListInfo ListInfo; + Info.SendDlgMessage(hDlg,DM_LISTINFO,LIST_BOX,reinterpret_cast(&ListInfo)); + if ((lstrlen(Filter) < sizeof(Filter)) && ListInfo.ItemsNumber) + { + int filterL = lstrlen(Filter); + Filter[filterL] = FSF.LLower(static_cast(Param2)); + Filter[filterL+1] = '\0'; + Info.SendDlgMessage(hDlg,DMU_UPDATE,0,0); + return TRUE; + } + } + } + } + return FALSE; + + case DN_CTLCOLORDIALOG: + return Info.AdvControl(Info.ModuleNumber,ACTL_GETCOLOR,(void *)COL_MENUTEXT); + + case DN_CTLCOLORDLGLIST: + if (Param1 == LIST_BOX) + { + FarListColors *Colors = (FarListColors *)Param2; + int ColorIndex[] = { COL_MENUBOX, COL_MENUBOX, COL_MENUTITLE, COL_MENUTEXT, COL_MENUHIGHLIGHT, COL_MENUBOX, COL_MENUSELECTEDTEXT, COL_MENUSELECTEDHIGHLIGHT, COL_MENUSCROLLBAR, COL_MENUDISABLEDTEXT, COL_MENUARROWS, COL_MENUARROWSSELECTED, COL_MENUARROWSDISABLED }; + int Count = ARRAYSIZE(ColorIndex); + if (Count > Colors->ColorCount) + Count = Colors->ColorCount; + for (int i = 0; i < Count; i++) + Colors->Colors[i] = static_cast(Info.AdvControl(Info.ModuleNumber, ACTL_GETCOLOR, reinterpret_cast(ColorIndex[i]))); + return TRUE; + } + break; + } + return Info.DefDlgProc(hDlg,Msg,Param1,Param2); +} + +HANDLE WINAPI OpenPlugin(int /*OpenFrom*/, INT_PTR /*Item*/) +{ + ReadRegistry(); + struct FarDialogItem DialogItems[1]; + ZeroMemory(DialogItems, sizeof(DialogItems)); + p = NULL; + FLI = NULL; + + hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + UpDateInfo(); + + DialogItems[0].Type = DI_LISTBOX; + DialogItems[0].Flags = DIF_LISTNOAMPERSAND; + DialogItems[0].X1 = 2; + DialogItems[0].Y1 = 1; + +#ifdef FARAPI17 + Info.DialogEx(Info.ModuleNumber,-1,-1,0,0,"Contents",DialogItems,ARRAYSIZE(DialogItems),0,0,DlgProc,0); +#endif +#ifdef FARAPI18 + HANDLE h_dlg = Info.DialogInit(Info.ModuleNumber,-1,-1,0,0,L"Contents",DialogItems,ARRAYSIZE(DialogItems),0,0,DlgProc,0); + if (h_dlg != INVALID_HANDLE_VALUE) { + Info.DialogRun(h_dlg); + Info.DialogFree(h_dlg); + } +#endif + FLI = (FarListItem *) realloc(FLI, 0); + p = (KeyInfo *) realloc(p, 0); + return INVALID_HANDLE_VALUE; +} + +int WINAPI Configure(int ItemNumber) +{ + PluginDialogBuilder Config(Info, MPlugIn, _T("Configuration")); + FarDialogItem *p1, *p2; + + BOOL bShowInViewer = (Opt.WhereWork & 1) != 0; + BOOL bShowInEditor = (Opt.WhereWork & 2) != 0; + //BOOL bEnterWaitCompletion = (Opt.EnterFunction != 0); + BOOL bUseElevation = (Opt.UseElevation != 0); + BOOL bLowPriority = (Opt.RunLowPriority != 0); + BOOL bForceMsiUse = (Opt.ForceMsiUse != 0); + + Config.AddCheckbox(MShowInEditor, &bShowInEditor); + Config.AddCheckbox(MShowInViewer, &bShowInViewer); + //Config.AddCheckbox(MEnterWaitCompletion, &bEnterWaitCompletion); + Config.AddCheckbox(MUseElevation, &bUseElevation); + Config.AddCheckbox(MLowPriority, &bUseElevation); + Config.AddCheckbox(MForceMsiUse, &bForceMsiUse); + + Config.AddSeparator(); + + FarList AEnter, AShiftEnter; + AEnter.ItemsNumber = AShiftEnter.ItemsNumber = 7; + AEnter.Items = (FarListItem*)calloc(AEnter.ItemsNumber,sizeof(FarListItem)); + AShiftEnter.Items = (FarListItem*)calloc(AEnter.ItemsNumber,sizeof(FarListItem)); + for (int i = 0; i < AEnter.ItemsNumber; i++) + { + #ifdef FARAPI18 + AEnter.Items[i].Text = GetMsg(MActionUninstallWait+i); + AShiftEnter.Items[i].Text = AEnter.Items[i].Text; + #else + StringCchCopy(AEnter.Items[i].Text,ARRAYSIZE(AEnter.Items[i].Text),GetMsg(MActionUninstallWait+i)); + StringCchCopy(AShiftEnter.Items[i].Text,ARRAYSIZE(AShiftEnter.Items[i].Text),AEnter.Items[i].Text); + #endif + } + + p1 = Config.AddText(MEnterAction); p2 = Config.AddComboBox(23, &AEnter, &Opt.EnterAction); + Config.MoveItemAfter(p1,p2); + p1 = Config.AddText(MShiftEnterAction); p2 = Config.AddComboBox(23, &AShiftEnter, &Opt.ShiftEnterAction); + Config.MoveItemAfter(p1,p2); + + + + Config.AddOKCancel(MBtnOk, MBtnCancel); + + if (Config.ShowDialog()) + { + Opt.WhereWork = (bShowInViewer ? 1 : 0) | (bShowInEditor ? 2 : 0); + //Opt.EnterFunction = bEnterWaitCompletion; + Opt.UseElevation = bUseElevation; + Opt.RunLowPriority = bLowPriority; + Opt.ForceMsiUse = bForceMsiUse; + + SetRegKey(HKCU,_T(""),_T("WhereWork"),(DWORD) Opt.WhereWork); + SetRegKey(HKCU,_T(""),_T("EnterAction"),(DWORD) Opt.EnterAction); + SetRegKey(HKCU,_T(""),_T("ShiftEnterAction"),(DWORD) Opt.ShiftEnterAction); + SetRegKey(HKCU,_T(""),_T("UseElevation"),(DWORD) Opt.UseElevation); + SetRegKey(HKCU,_T(""),_T("RunLowPriority"),(DWORD) Opt.RunLowPriority); + SetRegKey(HKCU,_T(""),_T("ForceMsiUse"),(DWORD) Opt.ForceMsiUse); + } + + return FALSE; +} diff --git a/Uninstall/src/UnInstall.hpp b/Uninstall/src/UnInstall.hpp index b871e94..72868f3 100644 --- a/Uninstall/src/UnInstall.hpp +++ b/Uninstall/src/UnInstall.hpp @@ -1,34 +1,40 @@ //дополнительные описания к ключам const TCHAR *HelpTopics[] = { - _T("DisplayName"), - _T(""), - _T("InstallLocation"), - _T("ModifyPath"), - _T("UninstallString"), - _T("Publisher"), - _T("URLInfoAbout"), - _T("URLUpdateInfo"), - _T("Comments"), - _T("DisplayVersion"), - _T("InstallDate") // Must be last item! + _T("DisplayName"), + _T(""), + _T("InstallLocation"), + _T("ModifyPath"), + _T("UninstallString"), + _T("Publisher"), + _T("URLInfoAbout"), + _T("URLUpdateInfo"), + _T("Comments"), + _T("DisplayVersion"), + _T("InstallDate") // Must be last item! +}; + +const TCHAR *HiddenPrefixes[] = +{ + _T("InstallWIX_{"), + _T("InstallShield_{") }; enum { - LIST_BOX, - DMU_UPDATE = DM_USER+1 + LIST_BOX, + DMU_UPDATE = DM_USER+1 }; enum ActionEnum { - Action_UninstallWait = 0, - Action_Uninstall, - Action_ModifyWait, - Action_Modify, - Action_RepairWait, - Action_Repair, - Action_Menu, + Action_UninstallWait = 0, + Action_Uninstall, + Action_ModifyWait, + Action_Modify, + Action_RepairWait, + Action_Repair, + Action_Menu, }; //enum ActionMenuEnum @@ -43,26 +49,28 @@ enum ActionEnum enum { - DisplayName, - RegLocation, - InstallLocation, - ModifyPath, - UninstallString, - Publisher, - URLInfoAbout, - URLUpdateInfo, - Comments, - DisplayVersion, - InstallDate + DisplayName, + RegLocation, + InstallLocation, + ModifyPath, + UninstallString, + Publisher, + URLInfoAbout, + URLUpdateInfo, + Comments, + DisplayVersion, + InstallDate }; const int KeysCount = ARRAYSIZE(HelpTopics); -struct RegKeyPath { - HKEY Root; - const TCHAR* Path; -} UninstKeys[] = { - { HKEY_CURRENT_USER, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall") }, - { HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall") }, +struct RegKeyPath +{ + HKEY Root; + const TCHAR* Path; +} UninstKeys[] = +{ + { HKEY_CURRENT_USER, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall") }, + { HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall") }, }; int nCount; // сколько всего элементов int nRealCount; // сколько выделено памяти @@ -73,190 +81,217 @@ HANDLE hStdout; struct Options { - int WhereWork; //<- TechInfo - //int EnterFunction; //<- TechInfo - int EnterAction; // enum ActionEnum - int ShiftEnterAction; // enum ActionEnum - int UseElevation; //<- TechInfo - int RunLowPriority; - int ForceMsiUse; - bool SortByDate; + int WhereWork; //<- TechInfo + //int EnterFunction; //<- TechInfo + int EnterAction; // enum ActionEnum + int ShiftEnterAction; // enum ActionEnum + int UseElevation; //<- TechInfo + int RunLowPriority; + int ForceMsiUse; + bool SortByDate; } Opt; struct KeyInfo { - TCHAR Keys[KeysCount][MAX_PATH]; + TCHAR Keys[KeysCount][MAX_PATH]; #ifdef FARAPI18 - TCHAR ListItem[MAX_PATH]; + TCHAR ListItem[MAX_PATH]; #endif - bool Avail[KeysCount]; - RegKeyPath RegKey; - FILETIME RegTime; - TCHAR InstDate[10]; - DWORD InstDateN; - REGSAM RegView; - TCHAR SubKeyName[MAX_PATH]; - bool WindowsInstaller; - bool Hidden; - bool NoModify, NoRepair; - bool CanModify, CanRepair; + bool Avail[KeysCount]; + RegKeyPath RegKey; + FILETIME RegTime; + TCHAR InstDate[10]; + DWORD InstDateN; + REGSAM RegView; + TCHAR SubKeyName[MAX_PATH]; + bool WindowsInstaller; + bool Hidden; + bool NoModify, NoRepair; + bool CanModify, CanRepair; } *p = NULL; bool ValidGuid(const TCHAR* guid) { - const unsigned c_max_guid_len = 38; - wchar_t buf[c_max_guid_len + 1]; - ZeroMemory(buf, sizeof(buf)); - unsigned l = lstrlen(guid); - for (unsigned i = 0; (i < c_max_guid_len) && (i < l); i++) buf[i] = guid[i]; - IID iid; - return IIDFromString(buf, &iid) == S_OK; + const unsigned c_max_guid_len = 38; + wchar_t buf[c_max_guid_len + 1]; + ZeroMemory(buf, sizeof(buf)); + unsigned l = lstrlen(guid); + + for(unsigned i = 0; (i < c_max_guid_len) && (i < l); i++) buf[i] = guid[i]; + + IID iid; + return IIDFromString(buf, &iid) == S_OK; } //чтение реестра bool FillReg(KeyInfo& key, TCHAR* Buf, RegKeyPath& RegKey, REGSAM RegView) { - HKEY userKey; - DWORD regType; - TCHAR fullN[MAX_PATH*2], *pszNamePtr; - LONG ExitCode; - DWORD bufSize, dwTest; - - memset(&key, 0, sizeof(key)); - - key.RegKey = RegKey; - key.RegView = RegView; - StringCchCopy(key.SubKeyName,ARRAYSIZE(key.SubKeyName),Buf); - StringCchCopy(fullN,ARRAYSIZE(fullN),key.RegKey.Path); - StringCchCat(fullN,ARRAYSIZE(fullN),_T("\\")); - pszNamePtr = fullN + _tcslen(fullN); - StringCchCat(fullN,ARRAYSIZE(fullN),key.SubKeyName); - if (RegOpenKeyEx(key.RegKey.Root, fullN, 0, KEY_READ | RegView, &userKey) != ERROR_SUCCESS) - return FALSE; - // "InstallWIX_{GUID}" - if (memcmp(key.SubKeyName, _T("InstallWIX_{"), 12*sizeof(TCHAR)) == 0 - && ValidGuid(key.SubKeyName+11)) - { - // Это может быть "ссылка" на гуид продукта - *pszNamePtr = 0; - StringCchCat(fullN,ARRAYSIZE(fullN),key.SubKeyName+11); - HKEY hTestKey; - if (RegOpenKeyEx(key.RegKey.Root, fullN, 0, KEY_READ | RegView, &hTestKey) == ERROR_SUCCESS) - { - key.Hidden = true; - RegCloseKey(hTestKey); - } - } - key.WindowsInstaller = (RegQueryValueEx(userKey,_T("WindowsInstaller"),0,NULL,NULL,NULL) == ERROR_SUCCESS) && ValidGuid(key.SubKeyName); - key.NoModify = (RegQueryValueEx(userKey,_T("NoModify"),0,NULL,(LPBYTE)&dwTest,&(bufSize)) == ERROR_SUCCESS) && (dwTest!=0); - key.NoRepair = (RegQueryValueEx(userKey,_T("NoRepair"),0,NULL,(LPBYTE)&dwTest,&(bufSize)) == ERROR_SUCCESS) && (dwTest!=0); - TCHAR sKeyTime[64]; int nKeyTimeLen; - if (RegQueryInfoKey(userKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&key.RegTime) != ERROR_SUCCESS) - { - memset(&key.RegTime, 0, sizeof(key.RegTime)); - //key.Keys[InstallDate][0] = 0; - sKeyTime[0] = 0; nKeyTimeLen = 0; - } - else - { - SYSTEMTIME st; FILETIME ft; - FileTimeToLocalFileTime(&key.RegTime, &ft); - FileTimeToSystemTime(&ft, &st); - StringCchPrintf(sKeyTime, ARRAYSIZE(sKeyTime), _T(" / %02u.%02u.%04u %u:%02u:%02u"), st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute, st.wSecond); - StringCchPrintf(key.InstDate, ARRAYSIZE(key.InstDate), _T("%02u.%02u.%02u"), st.wDay, st.wMonth, (st.wYear % 100)); - key.InstDateN = ((st.wYear & 0xFFFF) << 16) | ((st.wMonth & 0xFF) << 8) | (st.wDay & 0xFF); - nKeyTimeLen = lstrlen(sKeyTime) + 1; - } - for (int i=0;i(&item)); id++) - { - if (item.Type == DI_EDIT) - Info.SendDlgMessage(hDlg, DM_EDITUNCHANGEDFLAG, id, 0); - } - } - break; - case DN_KEY: - { - if ((Param2 == KEY_PGUP) || (Param2 == KEY_PGDN)) - { - TCHAR sMacro[32]; - if (Param2 == KEY_PGUP) - StringCchCopy(sMacro, ARRAYSIZE(sMacro), _T("Esc Up F3")); - else - StringCchCopy(sMacro, ARRAYSIZE(sMacro), _T("Esc Down F3")); - - ActlKeyMacro m = {MCMD_POSTMACROSTRING}; - m.Param.PlainText.SequenceText = sMacro; - m.Param.PlainText.Flags = KSFLAGS_DISABLEOUTPUT; - Info.AdvControl(Info.ModuleNumber, ACTL_KEYMACRO, &m); - - return TRUE; - } - } - break; - } - return Info.DefDlgProc(hDlg,Msg,Param1,Param2); + switch(Msg) + { + case DN_INITDIALOG: + { + FarDialogItem item; + + for(unsigned id = 0; Info.SendDlgMessage(hDlg, DM_GETDLGITEMSHORT, id, reinterpret_cast(&item)); id++) + { + if(item.Type == DI_EDIT) + Info.SendDlgMessage(hDlg, DM_EDITUNCHANGEDFLAG, id, 0); + } + } + break; + case DN_KEY: + { + if((Param2 == KEY_PGUP) || (Param2 == KEY_PGDN)) + { + TCHAR sMacro[32]; + + if(Param2 == KEY_PGUP) + StringCchCopy(sMacro, ARRAYSIZE(sMacro), _T("Esc Up F3")); + else + StringCchCopy(sMacro, ARRAYSIZE(sMacro), _T("Esc Down F3")); + + ActlKeyMacro m = {MCMD_POSTMACROSTRING}; + m.Param.PlainText.SequenceText = sMacro; + m.Param.PlainText.Flags = KSFLAGS_DISABLEOUTPUT; + Info.AdvControl(Info.ModuleNumber, ACTL_KEYMACRO, &m); + return TRUE; + } + } + break; + } + + return Info.DefDlgProc(hDlg,Msg,Param1,Param2); } //заполнение пункта диалога void FillDialog(FarDialogItem & DialogItem, int Type, int X1, int Y1, int X2, int Y2, int Flags, int nData) { - const TCHAR* s = nData != -1 ? GetMsg(nData) : _T(""); + const TCHAR* s = nData != -1 ? GetMsg(nData) : _T(""); #ifdef FARAPI17 - lstrcpy(DialogItem.Data, s); + lstrcpy(DialogItem.Data, s); #endif #ifdef FARAPI18 - DialogItem.PtrData = s; + DialogItem.PtrData = s; #endif - - DialogItem.X1 = X1; - DialogItem.X2 = X2; - DialogItem.Y1 = Y1; - DialogItem.Y2 = Y2; - - DialogItem.Flags = Flags; - DialogItem.Type = Type; - DialogItem.Selected = 0; - DialogItem.DefaultButton = 0; - DialogItem.Focus = 0; - - if (Type == DI_BUTTON) - { - DialogItem.DefaultButton = 1; - DialogItem.Focus = 1; - } + DialogItem.X1 = X1; + DialogItem.X2 = X2; + DialogItem.Y1 = Y1; + DialogItem.Y2 = Y2; + DialogItem.Flags = Flags; + DialogItem.Type = Type; + DialogItem.Selected = 0; + DialogItem.DefaultButton = 0; + DialogItem.Focus = 0; + + if(Type == DI_BUTTON) + { + DialogItem.DefaultButton = 1; + DialogItem.Focus = 1; + } } void DisplayEntry(int Sel) { - unsigned sx = 70; - - unsigned max_len = 0; - unsigned cnt = 0; - for (int i=0;i sx) sx = len + 3; - cnt++; - } - } - - unsigned con_sx = 80; - HANDLE con = GetStdHandle(STD_OUTPUT_HANDLE); - if (con != INVALID_HANDLE_VALUE) { - CONSOLE_SCREEN_BUFFER_INFO con_info; - if (GetConsoleScreenBufferInfo(con, &con_info)) { - con_sx = con_info.srWindow.Right - con_info.srWindow.Left + 1; - } - } - - if (sx + 10 > con_sx) sx = con_sx - 10; - unsigned sy = cnt * 2; - - unsigned di_cnt = cnt * 2 + 2; - FarDialogItem* DialogItems = new FarDialogItem[di_cnt]; - unsigned y = 2; - unsigned idx = 1; - for (int i=0;i sx) sx = len + 3; + + cnt++; + } + } + + unsigned con_sx = 80; + HANDLE con = GetStdHandle(STD_OUTPUT_HANDLE); + + if(con != INVALID_HANDLE_VALUE) + { + CONSOLE_SCREEN_BUFFER_INFO con_info; + + if(GetConsoleScreenBufferInfo(con, &con_info)) + { + con_sx = con_info.srWindow.Right - con_info.srWindow.Left + 1; + } + } + + if(sx + 10 > con_sx) sx = con_sx - 10; + + unsigned sy = cnt * 2; + unsigned di_cnt = cnt * 2 + 2; + FarDialogItem* DialogItems = new FarDialogItem[di_cnt]; + unsigned y = 2; + unsigned idx = 1; + + for(int i=0; i') || - wcschr(asFilePath, L'<') || - wcschr(asFilePath, L'|') - ) + if(wcschr(asFilePath, L'"') || + wcschr(asFilePath, L'>') || + wcschr(asFilePath, L'<') || + wcschr(asFilePath, L'|') + ) return FALSE; // Пропуск UNC "\\?\" - if (asFilePath[0] == L'\\' && asFilePath[1] == L'\\' && asFilePath[2] == L'?' && asFilePath[3] == L'\\') + if(asFilePath[0] == L'\\' && asFilePath[1] == L'\\' && asFilePath[2] == L'?' && asFilePath[3] == L'\\') asFilePath += 4; // Если asFilePath содержит два (и более) ":\" LPCWSTR pszColon = wcschr(asFilePath, L':'); - if (pszColon) + + if(pszColon) { // Если есть ":", то это должен быть путь вида "X:\xxx", т.е. ":" - второй символ - if (pszColon != (asFilePath+1)) + if(pszColon != (asFilePath+1)) return FALSE; - if (wcschr(pszColon+1, L':')) + + if(wcschr(pszColon+1, L':')) + return FALSE; + } + + if (abCheckFileExist) + { + DWORD dwErr = 0; + HANDLE hFile = CreateFile(asFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + dwErr = GetLastError(); + if (dwErr = ERROR_FILE_NOT_FOUND) + return FALSE; + } + BY_HANDLE_FILE_INFORMATION hfi = {}; + BOOL lbInfo = GetFileInformationByHandle(hFile, &hfi); + CloseHandle(hFile); + + if (!lbInfo || (hfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) return FALSE; } @@ -493,55 +571,63 @@ BOOL IsFilePath(LPCWSTR asFilePath) BOOL FirstArg(LPCTSTR asCmdLine, TCHAR* rsArg/*[MAX_PATH+1]*/, LPCTSTR* rsNextArg) { - LPCTSTR psCmdLine = asCmdLine; + LPCTSTR psCmdLine = asCmdLine; LPCTSTR pch = NULL; - TCHAR ch = *psCmdLine; - size_t nArgLen = 0; - - while (ch == _T(' ') || ch == _T('\t') || ch == _T('\r') || ch == _T('\n')) ch = *(++psCmdLine); - if (ch == 0) return FALSE; - - // аргумент начинается с " - if (ch == _T('"')) - { - psCmdLine++; - pch = wcschr(psCmdLine, _T('"')); - if (!pch) return FALSE; - while (pch[1] == _T('"')) - { - pch += 2; - pch = wcschr(pch, _T('"')); - if (!pch) return FALSE; - } - // Теперь в pch ссылка на последнюю " - } - else - { - // До конца строки или до первого пробела - //pch = wcschr(psCmdLine, _T(' ')); - // 09.06.2009 Maks - обломался на: cmd /c" echo Y " + TCHAR ch = *psCmdLine; + size_t nArgLen = 0; + + while(ch == _T(' ') || ch == _T('\t') || ch == _T('\r') || ch == _T('\n')) ch = *(++psCmdLine); + + if(ch == 0) return FALSE; + + // аргумент начинается с " + if(ch == _T('"')) + { + psCmdLine++; + pch = wcschr(psCmdLine, _T('"')); + + if(!pch) return FALSE; + + while(pch[1] == _T('"')) + { + pch += 2; + pch = wcschr(pch, _T('"')); + + if(!pch) return FALSE; + } + + // Теперь в pch ссылка на последнюю " + } + else + { + // До конца строки или до первого пробела + //pch = wcschr(psCmdLine, _T(' ')); + // 09.06.2009 Maks - обломался на: cmd /c" echo Y " pch = psCmdLine; + // Ищем обычным образом (до пробела/кавычки) - while (*pch && *pch!=_T(' ') && *pch!=_T('"')) pch++; + while(*pch && *pch!=_T(' ') && *pch!=_T('"')) pch++; + //if (!pch) pch = psCmdLine + lstrlenW(psCmdLine); // до конца строки - } - - nArgLen = pch - psCmdLine; - if (nArgLen > MAX_PATH) return FALSE; - - // Вернуть аргумент - memcpy(rsArg, psCmdLine, nArgLen*sizeof(TCHAR)); - rsArg[nArgLen] = 0; - - psCmdLine = pch; - - // Finalize - ch = *psCmdLine; // может указывать на закрывающую кавычку - if (ch == L'"') ch = *(++psCmdLine); - while (ch == L' ' || ch == L'\t' || ch == L'\r' || ch == L'\n') ch = *(++psCmdLine); - *rsNextArg = psCmdLine; - - return TRUE; + } + + nArgLen = pch - psCmdLine; + + if(nArgLen > MAX_PATH) return FALSE; + + // Вернуть аргумент + memcpy(rsArg, psCmdLine, nArgLen*sizeof(TCHAR)); + rsArg[nArgLen] = 0; + psCmdLine = pch; + // Finalize + ch = *psCmdLine; // может указывать на закрывающую кавычку + + if(ch == L'"') ch = *(++psCmdLine); + + while(ch == L' ' || ch == L'\t' || ch == L'\r' || ch == L'\n') ch = *(++psCmdLine); + + *rsNextArg = psCmdLine; + return TRUE; } int EntryMenu(int Sel, int& Action, bool& LowPriority, int nChkCount = 0) @@ -551,358 +637,398 @@ int EntryMenu(int Sel, int& Action, bool& LowPriority, int nChkCount = 0) #else #define SETITEM(i,s) items[i].Text.TextPtr = GetMsg(s); items[i].Flags |= MIF_USETEXTPTR #endif - FarMenuItemEx items[6]; memset(items, 0, sizeof(items)); - SETITEM(Action_UninstallWait, MActionUninstallWait); - SETITEM(Action_Uninstall, MActionUninstall); - if (nChkCount > 1) - items[Action_Uninstall].Flags |= MIF_DISABLE; - SETITEM(Action_ModifyWait, MActionModifyWait); - SETITEM(Action_Modify, MActionModify); - if (nChkCount > 1) - items[Action_Modify].Flags |= MIF_DISABLE; - else if (!p[Sel].CanModify) - { - items[Action_Modify].Flags |= MIF_DISABLE; - items[Action_ModifyWait].Flags |= MIF_DISABLE; - } - SETITEM(Action_RepairWait, MActionRepairWait); - SETITEM(Action_Repair, MActionRepair); - if (nChkCount > 1) - items[Action_Repair].Flags |= MIF_DISABLE; - else if (!p[Sel].CanRepair) - { - items[Action_Repair].Flags |= MIF_DISABLE; - items[Action_RepairWait].Flags |= MIF_DISABLE; - } - - int iRc; - int BreakCode; - int BreakKeys[2]={VK_F7,0}; - TCHAR szMenuTitle[MAX_PATH]; - - if (nChkCount > 1) - StringCchPrintf(szMenuTitle, ARRAYSIZE(szMenuTitle), GetMsg(MMenuTopLineN), nChkCount); - else - StringCchCopy(szMenuTitle, ARRAYSIZE(szMenuTitle), GetMsg(MMenuTopLine)); - - while (true) - { - iRc = Info.Menu(Info.ModuleNumber, -1,-1,0, FMENU_USEEXT|FMENU_WRAPMODE, szMenuTitle, - GetMsg(LowPriority ? MMenuBottomLine2 : MMenuBottomLine1), - _T("ActionMenu"), BreakKeys, &BreakCode, (struct FarMenuItem *)items, ARRAYSIZE(items)); - if (iRc < 0) - return -1; - if (BreakCode == 0) - { - LowPriority = !LowPriority; - for (UINT i = 0; i < ARRAYSIZE(items); i++) - { - if (i == iRc) - items[i].Flags |= MIF_SELECTED; - else - items[i].Flags &= ~MIF_SELECTED; - } - } - else - { - Action = iRc; - break; - } - } - - if ((Action & 0xFF) == Action_Menu) - return -1; // ошибка - - return Action; + FarMenuItemEx items[6]; memset(items, 0, sizeof(items)); + SETITEM(Action_UninstallWait, MActionUninstallWait); + SETITEM(Action_Uninstall, MActionUninstall); + + if(nChkCount > 1) + items[Action_Uninstall].Flags |= MIF_DISABLE; + + SETITEM(Action_ModifyWait, MActionModifyWait); + SETITEM(Action_Modify, MActionModify); + + if(nChkCount > 1) + items[Action_Modify].Flags |= MIF_DISABLE; + else if(!p[Sel].CanModify) + { + items[Action_Modify].Flags |= MIF_DISABLE; + items[Action_ModifyWait].Flags |= MIF_DISABLE; + } + + SETITEM(Action_RepairWait, MActionRepairWait); + SETITEM(Action_Repair, MActionRepair); + + if(nChkCount > 1) + items[Action_Repair].Flags |= MIF_DISABLE; + else if(!p[Sel].CanRepair) + { + items[Action_Repair].Flags |= MIF_DISABLE; + items[Action_RepairWait].Flags |= MIF_DISABLE; + } + + int iRc; + int BreakCode; + int BreakKeys[2]= {VK_F7,0}; + TCHAR szMenuTitle[MAX_PATH]; + + if(nChkCount > 1) + StringCchPrintf(szMenuTitle, ARRAYSIZE(szMenuTitle), GetMsg(MMenuTopLineN), nChkCount); + else + StringCchCopy(szMenuTitle, ARRAYSIZE(szMenuTitle), GetMsg(MMenuTopLine)); + + while(true) + { + iRc = Info.Menu(Info.ModuleNumber, -1,-1,0, FMENU_USEEXT|FMENU_WRAPMODE, szMenuTitle, + GetMsg(LowPriority ? MMenuBottomLine2 : MMenuBottomLine1), + _T("ActionMenu"), BreakKeys, &BreakCode, (struct FarMenuItem *)items, ARRAYSIZE(items)); + + if(iRc < 0) + return -1; + + if(BreakCode == 0) + { + LowPriority = !LowPriority; + + for(UINT i = 0; i < ARRAYSIZE(items); i++) + { + if(i == iRc) + items[i].Flags |= MIF_SELECTED; + else + items[i].Flags &= ~MIF_SELECTED; + } + } + else + { + Action = iRc; + break; + } + } + + if((Action & 0xFF) == Action_Menu) + return -1; // ошибка + + return Action; } int ExecuteEntry(int Sel, int Action, bool LowPriority) { - if ((Action & 0xFF) == Action_Menu) - { - if (EntryMenu(Sel, Action, LowPriority) < 0) - return -1; - if ((Action & 0xFF) == Action_Menu) - return -1; // ошибка - } - - int nWaitSucceeded = 0; - STARTUPINFO si; - PROCESS_INFORMATION pi; - HANDLE hScreen; //for SaveScreen/RestoreScreen - - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - ZeroMemory(&pi, sizeof(pi)); - - TCHAR cmd_line[MAX_PATH*2+1], cmd_file[MAX_PATH+1], cmd_parm[MAX_PATH*2+1]; - - LPCTSTR pszString = NULL; - - if ((Action == Action_ModifyWait) || (Action == Action_Modify)) - pszString = p[Sel].Keys[ModifyPath]; - //else if ((Action == Action_RepairWait) || (Action == Action_Repair)) - // pszString = NULL; - else if ((Action == Action_UninstallWait) || (Action == Action_Uninstall)) - { - if (!p[Sel].WindowsInstaller) - pszString = p[Sel].Keys[UninstallString]; - } - - if (pszString && !*pszString) - pszString = NULL; - - - if (p[Sel].WindowsInstaller && !(!Opt.ForceMsiUse && pszString)) - { - TCHAR szCode[6]; - if ((Action == Action_UninstallWait) || (Action == Action_Uninstall)) - StringCchCopy(szCode, ARRAYSIZE(szCode), _T(" /x ")); - else if ((Action == Action_RepairWait) || (Action == Action_Repair)) - StringCchCopy(szCode, ARRAYSIZE(szCode), _T(" /fa ")); - else //if ((Action == Action_ModifyWait) || (Action == Action_Modify)) - StringCchCopy(szCode, ARRAYSIZE(szCode), _T(" /i ")); - // Для CreateProcess - StringCchCopy(cmd_line, ARRAYSIZE(cmd_line), _T("msiexec")); - StringCchCat(cmd_line, ARRAYSIZE(cmd_line), szCode); - StringCchCat(cmd_line, ARRAYSIZE(cmd_line), p[Sel].SubKeyName); - // Для ShellExecuteEx - if (LowPriority) - { - StringCchCopy(cmd_file, ARRAYSIZE(cmd_parm), _T("cmd")); - StringCchCopy(cmd_parm, ARRAYSIZE(cmd_parm), _T("/c start /low ")); - StringCchCat(cmd_parm, ARRAYSIZE(cmd_parm), _T("msiexec")); - StringCchCat(cmd_parm, ARRAYSIZE(cmd_parm), szCode); - StringCchCat(cmd_parm, ARRAYSIZE(cmd_parm), p[Sel].SubKeyName); - } - else - { - StringCchCopy(cmd_file, ARRAYSIZE(cmd_file), _T("msiexec")); - StringCchCopy(cmd_parm, ARRAYSIZE(cmd_parm), szCode); - StringCchCat(cmd_parm, ARRAYSIZE(cmd_parm), p[Sel].SubKeyName); - } - } - else - { - if (pszString == NULL) - return 0; - // Для CreateProcess - StringCchCopy(cmd_line, ARRAYSIZE(cmd_line), pszString); - // Для ShellExecuteEx - if (LowPriority) - { - StringCchCopy(cmd_file, ARRAYSIZE(cmd_parm), _T("cmd")); - StringCchCopy(cmd_parm, ARRAYSIZE(cmd_parm), _T("/c start /low \"\" ")); - StringCchCat(cmd_parm, ARRAYSIZE(cmd_parm), pszString); - } - else - { - LPCTSTR psNextArg = NULL; - if (FirstArg(pszString, cmd_file, &psNextArg) - && IsFilePath(cmd_file)) - { - StringCchCopy(cmd_parm, ARRAYSIZE(cmd_parm), psNextArg); - } - else - { - StringCchCopy(cmd_file, ARRAYSIZE(cmd_file), pszString); - cmd_parm[0] = 0; - } - } - } - - hScreen = Info.SaveScreen(0,0,-1,-1); //Это необходимо сделать, т.к. после запущенных программ нужно обновить окно ФАРа - - BOOL ifCreate = FALSE, bElevationFailed = FALSE, bPriorityChanged = FALSE; - DWORD dwErr = 0; - - // MSI сам выполнит повышение прав когда потребуется - if (!p[Sel].WindowsInstaller && Opt.UseElevation && !IsUserAdmin()) - { - // Required elevation - SHELLEXECUTEINFO sei = {sizeof(SHELLEXECUTEINFO)}; - sei.fMask = SEE_MASK_NOCLOSEPROCESS; - sei.lpVerb = _T("runas"); - sei.lpFile = cmd_file; - sei.lpParameters = cmd_parm; - sei.nShow = LowPriority ? SW_MINIMIZE : SW_SHOWNORMAL; - ifCreate = ShellExecuteEx(&sei); - if (ifCreate) - pi.hProcess = sei.hProcess; - else - bElevationFailed = true; - } - - // Если Elevation не запускался - if (!ifCreate) - { - ifCreate = CreateProcess // Start the child process. - ( - NULL, // No module name (use command line). - cmd_line, // Command line. - NULL, // Process handle not inheritable. - NULL, // Thread handle not inheritable. - FALSE, // Set handle inheritance to FALSE. - LowPriority ? IDLE_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS, // Creation flags. - NULL, // Use parent's environment block. - NULL, // Use parent's starting directory. - &si, // Pointer to STARTUPINFO structure. - &pi // Pointer to PROCESS_INFORMATION structure. - ); - if (ifCreate) - bPriorityChanged = TRUE; - } - - if (!ifCreate) //not Create - { - dwErr = GetLastError(); - if ((dwErr == 0x2E4) && !bElevationFailed) - { - // Required elevation - SHELLEXECUTEINFO sei = {sizeof(SHELLEXECUTEINFO)}; - sei.fMask = SEE_MASK_NOCLOSEPROCESS; - sei.lpVerb = _T("runas"); - sei.lpFile = cmd_file; - sei.lpParameters = cmd_parm; - sei.nShow = LowPriority ? SW_MINIMIZE : SW_SHOWNORMAL; - ifCreate = ShellExecuteEx(&sei); - if (ifCreate) - pi.hProcess = sei.hProcess; - else - dwErr = GetLastError(); - } - if (!ifCreate) //not Create - { - TCHAR szErrCode[32]; - const TCHAR *pszErrInfo = szErrCode; - if (dwErr == 0x000004C7) - pszErrInfo = GetMsg(MCancelledByUser); - else - StringCchPrintf(szErrCode, ARRAYSIZE(szErrCode), _T("ErrorCode=0x%08X"), dwErr); - if (hScreen) - Info.RestoreScreen(hScreen); - DrawMessage(FMSG_WARNING, 1, "%s",GetMsg(MPlugIn),GetMsg(MRunProgErr),cmd_line,pszErrInfo,GetMsg(MBtnOk),NULL); - return -1; - } - } - - // -- не может, если был сделан Elevation, а если Elevation не было - то уже в CreateProcess - //if (pi.hProcess && LowPriority && !bPriorityChanged) - //{ - // bPriorityChanged = SetPriorityClass(pi.hProcess, IDLE_PRIORITY_CLASS); - // dwErr = GetLastError(); - //} - - TCHAR SaveTitle[MAX_PATH]; - GetConsoleTitle(SaveTitle,ARRAYSIZE(SaveTitle)); - SaveTitle[ARRAYSIZE(SaveTitle) - 1] = 0; - SetConsoleTitle(cmd_line); - - if (pi.hProcess) - { - // Wait until child process exits. - if ((Action == Action_UninstallWait) - || (Action == Action_ModifyWait) - || (Action == Action_RepairWait)) - { - DrawMessage(0, 0, "%s", GetMsg(MPlugIn), GetMsg(MWaitingCompletion), cmd_line,NULL); - nWaitSucceeded = 1; - while (true) - { - if (WaitForSingleObject(pi.hProcess, 500) == WAIT_OBJECT_0) - break; - if (CheckForEsc()) - { - nWaitSucceeded = 0; - break; - } - } - } - // Close process and thread handles. - CloseHandle(pi.hProcess); - } - if (pi.hThread) - CloseHandle(pi.hThread); - - SetConsoleTitle(SaveTitle); - - if (hScreen) - { - Info.RestoreScreen(NULL); - Info.RestoreScreen(hScreen); - } - return nWaitSucceeded; + if((Action & 0xFF) == Action_Menu) + { + if(EntryMenu(Sel, Action, LowPriority) < 0) + return -1; + + if((Action & 0xFF) == Action_Menu) + return -1; // ошибка + } + + int nWaitSucceeded = 0; + STARTUPINFO si; + PROCESS_INFORMATION pi; + HANDLE hScreen; //for SaveScreen/RestoreScreen + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); + TCHAR cmd_line[MAX_PATH*2+1], cmd_file[MAX_PATH+1], cmd_parm[MAX_PATH*2+1]; + LPCTSTR pszString = NULL; + + if((Action == Action_ModifyWait) || (Action == Action_Modify)) + pszString = p[Sel].Keys[ModifyPath]; + //else if ((Action == Action_RepairWait) || (Action == Action_Repair)) + // pszString = NULL; + else if((Action == Action_UninstallWait) || (Action == Action_Uninstall)) + { + if(!p[Sel].WindowsInstaller) + pszString = p[Sel].Keys[UninstallString]; + } + + if(pszString && !*pszString) + pszString = NULL; + + if(p[Sel].WindowsInstaller && !(!Opt.ForceMsiUse && pszString)) + { + TCHAR szCode[6]; + + if((Action == Action_UninstallWait) || (Action == Action_Uninstall)) + StringCchCopy(szCode, ARRAYSIZE(szCode), _T(" /x ")); + else if((Action == Action_RepairWait) || (Action == Action_Repair)) + StringCchCopy(szCode, ARRAYSIZE(szCode), _T(" /fa ")); + else //if ((Action == Action_ModifyWait) || (Action == Action_Modify)) + StringCchCopy(szCode, ARRAYSIZE(szCode), _T(" /i ")); + + // Для CreateProcess + StringCchCopy(cmd_line, ARRAYSIZE(cmd_line), _T("msiexec")); + StringCchCat(cmd_line, ARRAYSIZE(cmd_line), szCode); + StringCchCat(cmd_line, ARRAYSIZE(cmd_line), p[Sel].SubKeyName); + + // Для ShellExecuteEx + if(LowPriority) + { + StringCchCopy(cmd_file, ARRAYSIZE(cmd_parm), _T("cmd")); + StringCchCopy(cmd_parm, ARRAYSIZE(cmd_parm), _T("/c start /low ")); + StringCchCat(cmd_parm, ARRAYSIZE(cmd_parm), _T("msiexec")); + StringCchCat(cmd_parm, ARRAYSIZE(cmd_parm), szCode); + StringCchCat(cmd_parm, ARRAYSIZE(cmd_parm), p[Sel].SubKeyName); + } + else + { + StringCchCopy(cmd_file, ARRAYSIZE(cmd_file), _T("msiexec")); + StringCchCopy(cmd_parm, ARRAYSIZE(cmd_parm), szCode); + StringCchCat(cmd_parm, ARRAYSIZE(cmd_parm), p[Sel].SubKeyName); + } + } + else + { + if(pszString == NULL) + return 0; + + // Для CreateProcess + StringCchCopy(cmd_line, ARRAYSIZE(cmd_line), pszString); + + // Для ShellExecuteEx + if(LowPriority) + { + StringCchCopy(cmd_file, ARRAYSIZE(cmd_parm), _T("cmd")); + StringCchCopy(cmd_parm, ARRAYSIZE(cmd_parm), _T("/c start /low \"\" ")); + StringCchCat(cmd_parm, ARRAYSIZE(cmd_parm), pszString); + } + else + { + LPCTSTR psNextArg = NULL; + + if(FirstArg(pszString, cmd_file, &psNextArg) + && IsFilePath(cmd_file, true)) + { + StringCchCopy(cmd_parm, ARRAYSIZE(cmd_parm), psNextArg); + } + else + { + #ifdef _DEBUG + IsFilePath(pszString, true); + #endif + StringCchCopy(cmd_file, ARRAYSIZE(cmd_file), pszString); + cmd_parm[0] = 0; + } + } + } + + hScreen = Info.SaveScreen(0,0,-1,-1); //Это необходимо сделать, т.к. после запущенных программ нужно обновить окно ФАРа + BOOL ifCreate = FALSE, bElevationFailed = FALSE, bPriorityChanged = FALSE; + DWORD dwErr = 0; + + // MSI сам выполнит повышение прав когда потребуется + if(!p[Sel].WindowsInstaller && Opt.UseElevation && !IsUserAdmin()) + { + // Required elevation + SHELLEXECUTEINFO sei = {sizeof(SHELLEXECUTEINFO)}; + sei.fMask = SEE_MASK_NOCLOSEPROCESS; + sei.lpVerb = _T("runas"); + sei.lpFile = cmd_file; + sei.lpParameters = cmd_parm; + sei.nShow = LowPriority ? SW_MINIMIZE : SW_SHOWNORMAL; + ifCreate = ShellExecuteEx(&sei); + + if(ifCreate) + pi.hProcess = sei.hProcess; + else + bElevationFailed = true; + } + + // Если Elevation не запускался + if(!ifCreate) + { + ifCreate = CreateProcess // Start the child process. + ( + NULL, // No module name (use command line). + cmd_line, // Command line. + NULL, // Process handle not inheritable. + NULL, // Thread handle not inheritable. + FALSE, // Set handle inheritance to FALSE. + LowPriority ? IDLE_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS, // Creation flags. + NULL, // Use parent's environment block. + NULL, // Use parent's starting directory. + &si, // Pointer to STARTUPINFO structure. + &pi // Pointer to PROCESS_INFORMATION structure. + ); + + if(ifCreate) + bPriorityChanged = TRUE; + } + + if(!ifCreate) //not Create + { + dwErr = GetLastError(); + + if((dwErr == 0x2E4) && !bElevationFailed) + { + // Required elevation + SHELLEXECUTEINFO sei = {sizeof(SHELLEXECUTEINFO)}; + sei.fMask = SEE_MASK_NOCLOSEPROCESS; + sei.lpVerb = _T("runas"); + sei.lpFile = cmd_file; + sei.lpParameters = cmd_parm; + sei.nShow = LowPriority ? SW_MINIMIZE : SW_SHOWNORMAL; + ifCreate = ShellExecuteEx(&sei); + + if(ifCreate) + pi.hProcess = sei.hProcess; + else + dwErr = GetLastError(); + } + + if(!ifCreate) //not Create + { + TCHAR szErrCode[32]; + const TCHAR *pszErrInfo = szErrCode; + + if(dwErr == 0x000004C7) + pszErrInfo = GetMsg(MCancelledByUser); + else + StringCchPrintf(szErrCode, ARRAYSIZE(szErrCode), _T("ErrorCode=0x%08X"), dwErr); + + if(hScreen) + Info.RestoreScreen(hScreen); + + DrawMessage(FMSG_WARNING, 1, "%s",GetMsg(MPlugIn),GetMsg(MRunProgErr),cmd_line,pszErrInfo,GetMsg(MBtnOk),NULL); + return -1; + } + } + + // -- не может, если был сделан Elevation, а если Elevation не было - то уже в CreateProcess + //if (pi.hProcess && LowPriority && !bPriorityChanged) + //{ + // bPriorityChanged = SetPriorityClass(pi.hProcess, IDLE_PRIORITY_CLASS); + // dwErr = GetLastError(); + //} + TCHAR SaveTitle[MAX_PATH]; + GetConsoleTitle(SaveTitle,ARRAYSIZE(SaveTitle)); + SaveTitle[ARRAYSIZE(SaveTitle) - 1] = 0; + SetConsoleTitle(cmd_line); + + if(pi.hProcess) + { + // Wait until child process exits. + if((Action == Action_UninstallWait) + || (Action == Action_ModifyWait) + || (Action == Action_RepairWait)) + { + DrawMessage(0, 0, "%s", GetMsg(MPlugIn), GetMsg(MWaitingCompletion), cmd_line,NULL); + nWaitSucceeded = 1; + + while(true) + { + if(WaitForSingleObject(pi.hProcess, 500) == WAIT_OBJECT_0) + break; + + if(CheckForEsc()) + { + nWaitSucceeded = 0; + break; + } + } + } + + // Close process and thread handles. + CloseHandle(pi.hProcess); + } + + if(pi.hThread) + CloseHandle(pi.hThread); + + SetConsoleTitle(SaveTitle); + + if(hScreen) + { + Info.RestoreScreen(NULL); + Info.RestoreScreen(hScreen); + } + + return nWaitSucceeded; } -typedef WINADVAPI LSTATUS (APIENTRY *FRegDeleteKeyExA)(__in HKEY hKey, __in LPCSTR lpSubKey, __in REGSAM samDesired, __reserved DWORD Reserved); -typedef WINADVAPI LSTATUS (APIENTRY *FRegDeleteKeyExW)(__in HKEY hKey, __in LPCWSTR lpSubKey, __in REGSAM samDesired, __reserved DWORD Reserved); +typedef WINADVAPI LSTATUS(APIENTRY *FRegDeleteKeyExA)(__in HKEY hKey, __in LPCSTR lpSubKey, __in REGSAM samDesired, __reserved DWORD Reserved); +typedef WINADVAPI LSTATUS(APIENTRY *FRegDeleteKeyExW)(__in HKEY hKey, __in LPCWSTR lpSubKey, __in REGSAM samDesired, __reserved DWORD Reserved); bool DeleteEntry(int Sel) { - HMODULE h_mod = LoadLibrary(_T("advapi32.dll")); - FRegDeleteKeyExA RegDeleteKeyExA = reinterpret_cast(GetProcAddress(h_mod, "RegDeleteKeyExA")); - FRegDeleteKeyExW RegDeleteKeyExW = reinterpret_cast(GetProcAddress(h_mod, "RegDeleteKeyExW")); - FreeLibrary(h_mod); - - HKEY userKey; - LONG ret = RegOpenKeyEx(p[Sel].RegKey.Root, p[Sel].RegKey.Path, 0, DELETE | p[Sel].RegView, &userKey); - if (ret != ERROR_SUCCESS) return false; - if (RegDeleteKeyEx) - ret = RegDeleteKeyEx(userKey, p[Sel].SubKeyName, p[Sel].RegView, 0); - else - ret = RegDeleteKey(userKey, p[Sel].SubKeyName); - RegCloseKey(userKey); - if (ret != ERROR_SUCCESS) return false; - return true; + HMODULE h_mod = LoadLibrary(_T("advapi32.dll")); + FRegDeleteKeyExA RegDeleteKeyExA = reinterpret_cast(GetProcAddress(h_mod, "RegDeleteKeyExA")); + FRegDeleteKeyExW RegDeleteKeyExW = reinterpret_cast(GetProcAddress(h_mod, "RegDeleteKeyExW")); + FreeLibrary(h_mod); + HKEY userKey; + LONG ret = RegOpenKeyEx(p[Sel].RegKey.Root, p[Sel].RegKey.Path, 0, DELETE | p[Sel].RegView, &userKey); + + if(ret != ERROR_SUCCESS) return false; + + if(RegDeleteKeyEx) + ret = RegDeleteKeyEx(userKey, p[Sel].SubKeyName, p[Sel].RegView, 0); + else + ret = RegDeleteKey(userKey, p[Sel].SubKeyName); + + RegCloseKey(userKey); + + if(ret != ERROR_SUCCESS) return false; + + return true; } //сравнить строки int __cdecl CompareEntries(const void* item1, const void* item2) { - return FSF.LStricmp(reinterpret_cast(item1)->Keys[DisplayName], reinterpret_cast(item2)->Keys[DisplayName]); + return FSF.LStricmp(reinterpret_cast(item1)->Keys[DisplayName], reinterpret_cast(item2)->Keys[DisplayName]); } //сравнить даты int __cdecl CompareEntriesDate(const void* item1, const void* item2) { - if (reinterpret_cast(item1)->InstDateN < reinterpret_cast(item2)->InstDateN) - return 1; - if (reinterpret_cast(item1)->InstDateN > reinterpret_cast(item2)->InstDateN) - return -1; - return CompareEntries(item1, item2); + if(reinterpret_cast(item1)->InstDateN < reinterpret_cast(item2)->InstDateN) + return 1; + + if(reinterpret_cast(item1)->InstDateN > reinterpret_cast(item2)->InstDateN) + return -1; + + return CompareEntries(item1, item2); } #define JUMPREALLOC 50 -void EnumKeys(RegKeyPath& RegKey, REGSAM RegView = 0) { - HKEY hKey; - if (RegOpenKeyEx(RegKey.Root, RegKey.Path, 0, KEY_READ | RegView, &hKey) != ERROR_SUCCESS) - return; - DWORD cSubKeys; - if (RegQueryInfoKey(hKey,NULL,NULL,NULL,&cSubKeys,NULL,NULL,NULL,NULL,NULL,NULL,NULL) != ERROR_SUCCESS) - return; - - TCHAR Buf[MAX_PATH]; - for (DWORD fEnumIndex=0; fEnumIndex= nRealCount) - { - nRealCount += JUMPREALLOC; - p = (KeyInfo *) realloc(p, sizeof(KeyInfo) * nRealCount); - } - if (FillReg(p[nCount], Buf, RegKey, RegView)) - { +void EnumKeys(RegKeyPath& RegKey, REGSAM RegView = 0) +{ + HKEY hKey; + + if(RegOpenKeyEx(RegKey.Root, RegKey.Path, 0, KEY_READ | RegView, &hKey) != ERROR_SUCCESS) + return; + + DWORD cSubKeys; + + if(RegQueryInfoKey(hKey,NULL,NULL,NULL,&cSubKeys,NULL,NULL,NULL,NULL,NULL,NULL,NULL) != ERROR_SUCCESS) + return; + + TCHAR Buf[MAX_PATH]; + + for(DWORD fEnumIndex=0; fEnumIndex= nRealCount) + { + nRealCount += JUMPREALLOC; + p = (KeyInfo *) realloc(p, sizeof(KeyInfo) * nRealCount); + } + + if(FillReg(p[nCount], Buf, RegKey, RegView)) + { #ifdef FARAPI17 - CharToOem(p[nCount].Keys[DisplayName], p[nCount].Keys[DisplayName]); - CharToOem(p[nCount].Keys[UninstallString], p[nCount].Keys[UninstallString]); - CharToOem(p[nCount].Keys[ModifyPath], p[nCount].Keys[ModifyPath]); + CharToOem(p[nCount].Keys[DisplayName], p[nCount].Keys[DisplayName]); + CharToOem(p[nCount].Keys[UninstallString], p[nCount].Keys[UninstallString]); + CharToOem(p[nCount].Keys[ModifyPath], p[nCount].Keys[ModifyPath]); #endif - nCount++; - } - } - RegCloseKey(hKey); + nCount++; + } + } + + RegCloseKey(hKey); } #undef JUMPREALLOC @@ -912,109 +1038,108 @@ typedef WINBASEAPI VOID (WINAPI *FGetNativeSystemInfo)(__out LPSYSTEM_INFO lpSys //Обновление информации void UpDateInfo(void) { - HMODULE h_mod = LoadLibrary(_T("kernel32.dll")); - FGetNativeSystemInfo GetNativeSystemInfo = reinterpret_cast(GetProcAddress(h_mod, "GetNativeSystemInfo")); - FreeLibrary(h_mod); - bool is_os_x64 = false; - if (GetNativeSystemInfo) - { - SYSTEM_INFO si; - GetNativeSystemInfo(&si); - is_os_x64 = si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64; - } - - nCount = nRealCount = 0; - for (int i=0;i(GetProcAddress(h_mod, "GetNativeSystemInfo")); + FreeLibrary(h_mod); + bool is_os_x64 = false; + + if(GetNativeSystemInfo) + { + SYSTEM_INFO si; + GetNativeSystemInfo(&si); + is_os_x64 = si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64; + } + + nCount = nRealCount = 0; + + for(int i=0; i(FLI[i].Text); - - if (FirstChar[1] != FSF.LUpper(p[i].Keys[DisplayName][0])) - { - FirstChar[1] = FSF.LUpper(p[i].Keys[DisplayName][0]); - StringCchCopy(text, MaxSize, FirstChar); - } - else - StringCchCopy(text, MaxSize, EMPTYSTR); - - if (p[i].RegKey.Root == HKEY_LOCAL_MACHINE) - { - if (is_os_x64) - StringCchCat(text, MaxSize, (p[i].RegView == KEY_WOW64_64KEY) ? sx64 : sx86); - else - StringCchCat(text, MaxSize, sHKLM); - } - else - StringCchCat(text, MaxSize, sHKCU); - - StringCchCat(text, MaxSize, _T(" ")); - StringCchCat(text, MaxSize, p[i].InstDate); - StringCchCat(text, MaxSize, _T(" ")); - StringCchCat(text, MaxSize, (p[i].WindowsInstaller) ? _T("W") : _T(" ")); - StringCchCat(text, MaxSize, (p[i].CanModify) ? _T("M") : _T(" ")); - StringCchCat(text, MaxSize, (p[i].CanRepair) ? _T("R") : _T(" ")); - StringCchCat(text, MaxSize, (p[i].Hidden) ? _T("-") : _T(" ")); - StringCchCat(text, MaxSize, _T(" ")); - - //if ((p[i].Keys[ModifyPath][0] == 0) && (p[i].Keys[UninstallString][0] == 0)) - //if (p[i].Hidden) - // StringCchCat(text, MaxSize, _T(" - ")); - //else - // StringCchCat(text, MaxSize, _T(" ")); - - size_t nCurLen = _tcslen(text); - //StringCchCat(text, MaxSize, p[i].Keys[DisplayName]); - StringCchCopyN(text+nCurLen, MaxSize-nCurLen, p[i].Keys[DisplayName], MaxSize-nCurLen-1); - text[MaxSize-1] = 0; - } - - ListSize = nCount; + TCHAR* text = const_cast(FLI[i].Text); + + if(FirstChar[1] != FSF.LUpper(p[i].Keys[DisplayName][0])) + { + FirstChar[1] = FSF.LUpper(p[i].Keys[DisplayName][0]); + StringCchCopy(text, MaxSize, FirstChar); + } + else + StringCchCopy(text, MaxSize, EMPTYSTR); + + if(p[i].RegKey.Root == HKEY_LOCAL_MACHINE) + { + if(is_os_x64) + StringCchCat(text, MaxSize, (p[i].RegView == KEY_WOW64_64KEY) ? sx64 : sx86); + else + StringCchCat(text, MaxSize, sHKLM); + } + else + StringCchCat(text, MaxSize, sHKCU); + + StringCchCat(text, MaxSize, _T(" ")); + StringCchCat(text, MaxSize, p[i].InstDate); + StringCchCat(text, MaxSize, _T(" ")); + StringCchCat(text, MaxSize, (p[i].WindowsInstaller) ? _T("W") : _T(" ")); + StringCchCat(text, MaxSize, (p[i].CanModify) ? _T("M") : _T(" ")); + StringCchCat(text, MaxSize, (p[i].CanRepair) ? _T("R") : _T(" ")); + StringCchCat(text, MaxSize, (p[i].Hidden) ? _T("-") : _T(" ")); + StringCchCat(text, MaxSize, _T(" ")); + //if ((p[i].Keys[ModifyPath][0] == 0) && (p[i].Keys[UninstallString][0] == 0)) + //if (p[i].Hidden) + // StringCchCat(text, MaxSize, _T(" - ")); + //else + // StringCchCat(text, MaxSize, _T(" ")); + size_t nCurLen = _tcslen(text); + //StringCchCat(text, MaxSize, p[i].Keys[DisplayName]); + StringCchCopyN(text+nCurLen, MaxSize-nCurLen, p[i].Keys[DisplayName], MaxSize-nCurLen-1); + text[MaxSize-1] = 0; + } + + ListSize = nCount; } #undef EMPTYSTR @@ -1022,36 +1147,41 @@ void UpDateInfo(void) void ReadRegistry() { - //TechInfo - if (GetRegKey(HKCU,_T(""),_T("WhereWork"),Opt.WhereWork,3)) - if ((Opt.WhereWork<0) || (Opt.WhereWork>3)) - Opt.WhereWork=3; - SetRegKey(HKCU,_T(""),_T("WhereWork"),(DWORD) Opt.WhereWork); - - if (GetRegKey(HKCU,_T(""),_T("EnterAction"),Opt.EnterAction,Action_Menu)) - if ((Opt.EnterAction<0) || (Opt.EnterAction>Action_Menu)) - Opt.EnterAction = Action_Menu; - SetRegKey(HKCU,_T(""),_T("EnterAction"),(DWORD) Opt.EnterAction); - - if (GetRegKey(HKCU,_T(""),_T("ShiftEnterAction"),Opt.ShiftEnterAction,Action_UninstallWait)) - if ((Opt.ShiftEnterAction<0) || (Opt.ShiftEnterAction>Action_Menu)) - Opt.ShiftEnterAction = Action_Menu; - SetRegKey(HKCU,_T(""),_T("ShiftEnterAction"),(DWORD) Opt.ShiftEnterAction); - - if (GetRegKey(HKCU,_T(""),_T("UseElevation"),Opt.UseElevation,1)) - if ((Opt.UseElevation<0) || (Opt.UseElevation>1)) - Opt.UseElevation=1; - SetRegKey(HKCU,_T(""),_T("UseElevation"),(DWORD) Opt.UseElevation); - - if (GetRegKey(HKCU,_T(""),_T("RunLowPriority"),Opt.RunLowPriority,0)) - if ((Opt.RunLowPriority<0) || (Opt.RunLowPriority>1)) - Opt.RunLowPriority=0; - SetRegKey(HKCU,_T(""),_T("RunLowPriority"),(DWORD) Opt.RunLowPriority); - - if (GetRegKey(HKCU,_T(""),_T("ForceMsiUse"),Opt.ForceMsiUse,0)) - if ((Opt.ForceMsiUse<0) || (Opt.ForceMsiUse>1)) - Opt.ForceMsiUse=0; - SetRegKey(HKCU,_T(""),_T("ForceMsiUse"),(DWORD) Opt.ForceMsiUse); - - Opt.SortByDate = false; + //TechInfo + if(GetRegKey(HKCU,_T(""),_T("WhereWork"),Opt.WhereWork,3)) + if((Opt.WhereWork<0) || (Opt.WhereWork>3)) + Opt.WhereWork=3; + + SetRegKey(HKCU,_T(""),_T("WhereWork"),(DWORD) Opt.WhereWork); + + if(GetRegKey(HKCU,_T(""),_T("EnterAction"),Opt.EnterAction,Action_Menu)) + if((Opt.EnterAction<0) || (Opt.EnterAction>Action_Menu)) + Opt.EnterAction = Action_Menu; + + SetRegKey(HKCU,_T(""),_T("EnterAction"),(DWORD) Opt.EnterAction); + + if(GetRegKey(HKCU,_T(""),_T("ShiftEnterAction"),Opt.ShiftEnterAction,Action_UninstallWait)) + if((Opt.ShiftEnterAction<0) || (Opt.ShiftEnterAction>Action_Menu)) + Opt.ShiftEnterAction = Action_Menu; + + SetRegKey(HKCU,_T(""),_T("ShiftEnterAction"),(DWORD) Opt.ShiftEnterAction); + + if(GetRegKey(HKCU,_T(""),_T("UseElevation"),Opt.UseElevation,1)) + if((Opt.UseElevation<0) || (Opt.UseElevation>1)) + Opt.UseElevation=1; + + SetRegKey(HKCU,_T(""),_T("UseElevation"),(DWORD) Opt.UseElevation); + + if(GetRegKey(HKCU,_T(""),_T("RunLowPriority"),Opt.RunLowPriority,0)) + if((Opt.RunLowPriority<0) || (Opt.RunLowPriority>1)) + Opt.RunLowPriority=0; + + SetRegKey(HKCU,_T(""),_T("RunLowPriority"),(DWORD) Opt.RunLowPriority); + + if(GetRegKey(HKCU,_T(""),_T("ForceMsiUse"),Opt.ForceMsiUse,0)) + if((Opt.ForceMsiUse<0) || (Opt.ForceMsiUse>1)) + Opt.ForceMsiUse=0; + + SetRegKey(HKCU,_T(""),_T("ForceMsiUse"),(DWORD) Opt.ForceMsiUse); + Opt.SortByDate = false; } diff --git a/Uninstall/src/UnInstall.hpp.orig b/Uninstall/src/UnInstall.hpp.orig new file mode 100644 index 0000000..bd3d6d6 --- /dev/null +++ b/Uninstall/src/UnInstall.hpp.orig @@ -0,0 +1,1070 @@ +//дополнительные описания к ключам +const TCHAR *HelpTopics[] = +{ + _T("DisplayName"), + _T(""), + _T("InstallLocation"), + _T("ModifyPath"), + _T("UninstallString"), + _T("Publisher"), + _T("URLInfoAbout"), + _T("URLUpdateInfo"), + _T("Comments"), + _T("DisplayVersion"), + _T("InstallDate") // Must be last item! +}; + +const TCHAR *HiddenPrefixes[] = +{ + _T("InstallWIX_{"), + _T("InstallShield_{") +}; + +enum +{ + LIST_BOX, + DMU_UPDATE = DM_USER+1 +}; + +enum ActionEnum +{ + Action_UninstallWait = 0, + Action_Uninstall, + Action_ModifyWait, + Action_Modify, + Action_RepairWait, + Action_Repair, + Action_Menu, +}; + +//enum ActionMenuEnum +//{ +// ActionMenu_UninstallWait = 0, +// ActionMenu_Uninstall, +// ActionMenu_ModifyWait, +// ActionMenu_Modify, +// ActionMenu_RepairWait, +// ActionMenu_Repair, +//}; + +enum +{ + DisplayName, + RegLocation, + InstallLocation, + ModifyPath, + UninstallString, + Publisher, + URLInfoAbout, + URLUpdateInfo, + Comments, + DisplayVersion, + InstallDate +}; + +const int KeysCount = ARRAYSIZE(HelpTopics); +struct RegKeyPath { + HKEY Root; + const TCHAR* Path; +} UninstKeys[] = { + { HKEY_CURRENT_USER, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall") }, + { HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall") }, +}; +int nCount; // сколько всего элементов +int nRealCount; // сколько выделено памяти +FarList FL; +FarListItem* FLI = NULL; +int ListSize; +HANDLE hStdout; + +struct Options +{ + int WhereWork; //<- TechInfo + //int EnterFunction; //<- TechInfo + int EnterAction; // enum ActionEnum + int ShiftEnterAction; // enum ActionEnum + int UseElevation; //<- TechInfo + int RunLowPriority; + int ForceMsiUse; + bool SortByDate; +} Opt; + +struct KeyInfo +{ + TCHAR Keys[KeysCount][MAX_PATH]; +#ifdef FARAPI18 + TCHAR ListItem[MAX_PATH]; +#endif + bool Avail[KeysCount]; + RegKeyPath RegKey; + FILETIME RegTime; + TCHAR InstDate[10]; + DWORD InstDateN; + REGSAM RegView; + TCHAR SubKeyName[MAX_PATH]; + bool WindowsInstaller; + bool Hidden; + bool NoModify, NoRepair; + bool CanModify, CanRepair; +} *p = NULL; + +bool ValidGuid(const TCHAR* guid) +{ + const unsigned c_max_guid_len = 38; + wchar_t buf[c_max_guid_len + 1]; + ZeroMemory(buf, sizeof(buf)); + unsigned l = lstrlen(guid); + for (unsigned i = 0; (i < c_max_guid_len) && (i < l); i++) buf[i] = guid[i]; + IID iid; + return IIDFromString(buf, &iid) == S_OK; +} + +//чтение реестра +bool FillReg(KeyInfo& key, TCHAR* Buf, RegKeyPath& RegKey, REGSAM RegView) +{ + HKEY userKey; + DWORD regType; + TCHAR fullN[MAX_PATH*2], *pszNamePtr; + LONG ExitCode; + DWORD bufSize, dwTest; + + memset(&key, 0, sizeof(key)); + + key.RegKey = RegKey; + key.RegView = RegView; + StringCchCopy(key.SubKeyName,ARRAYSIZE(key.SubKeyName),Buf); + StringCchCopy(fullN,ARRAYSIZE(fullN),key.RegKey.Path); + StringCchCat(fullN,ARRAYSIZE(fullN),_T("\\")); + pszNamePtr = fullN + _tcslen(fullN); + StringCchCat(fullN,ARRAYSIZE(fullN),key.SubKeyName); + if (RegOpenKeyEx(key.RegKey.Root, fullN, 0, KEY_READ | RegView, &userKey) != ERROR_SUCCESS) + return FALSE; + // "InstallWIX_{GUID}", "InstallShield_{" + for (int h = 0; h < ARRAYSIZE(HiddenPrefixes); h++) + { + int nPrefixLen = lstrlen(HiddenPrefixes[h]); + if (memcmp(key.SubKeyName, HiddenPrefixes[h], nPrefixLen*sizeof(TCHAR)) == 0 + && ValidGuid(key.SubKeyName+nPrefixLen-1)) + { + // Это может быть "ссылка" на гуид продукта + *pszNamePtr = 0; + StringCchCat(fullN,ARRAYSIZE(fullN),key.SubKeyName+nPrefixLen-1); + HKEY hTestKey; + if (RegOpenKeyEx(key.RegKey.Root, fullN, 0, KEY_READ | RegView, &hTestKey) == ERROR_SUCCESS) + { + key.Hidden = true; + RegCloseKey(hTestKey); + } + } + } + key.WindowsInstaller = (RegQueryValueEx(userKey,_T("WindowsInstaller"),0,NULL,NULL,NULL) == ERROR_SUCCESS) && ValidGuid(key.SubKeyName); + key.NoModify = (RegQueryValueEx(userKey,_T("NoModify"),0,NULL,(LPBYTE)&dwTest,&(bufSize)) == ERROR_SUCCESS) && (dwTest!=0); + key.NoRepair = (RegQueryValueEx(userKey,_T("NoRepair"),0,NULL,(LPBYTE)&dwTest,&(bufSize)) == ERROR_SUCCESS) && (dwTest!=0); + TCHAR sKeyTime[64]; int nKeyTimeLen; + if (RegQueryInfoKey(userKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&key.RegTime) != ERROR_SUCCESS) + { + memset(&key.RegTime, 0, sizeof(key.RegTime)); + //key.Keys[InstallDate][0] = 0; + sKeyTime[0] = 0; nKeyTimeLen = 0; + } + else + { + SYSTEMTIME st; FILETIME ft; + FileTimeToLocalFileTime(&key.RegTime, &ft); + FileTimeToSystemTime(&ft, &st); + StringCchPrintf(sKeyTime, ARRAYSIZE(sKeyTime), _T(" / %02u.%02u.%04u %u:%02u:%02u"), st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute, st.wSecond); + StringCchPrintf(key.InstDate, ARRAYSIZE(key.InstDate), _T("%02u.%02u.%02u"), st.wDay, st.wMonth, (st.wYear % 100)); + key.InstDateN = ((st.wYear & 0xFFFF) << 16) | ((st.wMonth & 0xFF) << 8) | (st.wDay & 0xFF); + nKeyTimeLen = lstrlen(sKeyTime) + 1; + } + for (int i=0;i(&item)); id++) + { + if (item.Type == DI_EDIT) + Info.SendDlgMessage(hDlg, DM_EDITUNCHANGEDFLAG, id, 0); + } + } + break; + case DN_KEY: + { + if ((Param2 == KEY_PGUP) || (Param2 == KEY_PGDN)) + { + TCHAR sMacro[32]; + if (Param2 == KEY_PGUP) + StringCchCopy(sMacro, ARRAYSIZE(sMacro), _T("Esc Up F3")); + else + StringCchCopy(sMacro, ARRAYSIZE(sMacro), _T("Esc Down F3")); + + ActlKeyMacro m = {MCMD_POSTMACROSTRING}; + m.Param.PlainText.SequenceText = sMacro; + m.Param.PlainText.Flags = KSFLAGS_DISABLEOUTPUT; + Info.AdvControl(Info.ModuleNumber, ACTL_KEYMACRO, &m); + + return TRUE; + } + } + break; + } + return Info.DefDlgProc(hDlg,Msg,Param1,Param2); +} + +//заполнение пункта диалога +void FillDialog(FarDialogItem & DialogItem, int Type, int X1, int Y1, int X2, int Y2, + int Flags, int nData) +{ + const TCHAR* s = nData != -1 ? GetMsg(nData) : _T(""); +#ifdef FARAPI17 + lstrcpy(DialogItem.Data, s); +#endif +#ifdef FARAPI18 + DialogItem.PtrData = s; +#endif + + DialogItem.X1 = X1; + DialogItem.X2 = X2; + DialogItem.Y1 = Y1; + DialogItem.Y2 = Y2; + + DialogItem.Flags = Flags; + DialogItem.Type = Type; + DialogItem.Selected = 0; + DialogItem.DefaultButton = 0; + DialogItem.Focus = 0; + + if (Type == DI_BUTTON) + { + DialogItem.DefaultButton = 1; + DialogItem.Focus = 1; + } +} + +void DisplayEntry(int Sel) +{ + unsigned sx = 70; + + unsigned max_len = 0; + unsigned cnt = 0; + for (int i=0;i sx) sx = len + 3; + cnt++; + } + } + + unsigned con_sx = 80; + HANDLE con = GetStdHandle(STD_OUTPUT_HANDLE); + if (con != INVALID_HANDLE_VALUE) { + CONSOLE_SCREEN_BUFFER_INFO con_info; + if (GetConsoleScreenBufferInfo(con, &con_info)) { + con_sx = con_info.srWindow.Right - con_info.srWindow.Left + 1; + } + } + + if (sx + 10 > con_sx) sx = con_sx - 10; + unsigned sy = cnt * 2; + + unsigned di_cnt = cnt * 2 + 2; + FarDialogItem* DialogItems = new FarDialogItem[di_cnt]; + unsigned y = 2; + unsigned idx = 1; + for (int i=0;i') || + wcschr(asFilePath, L'<') || + wcschr(asFilePath, L'|') + ) + return FALSE; + + // Пропуск UNC "\\?\" + if (asFilePath[0] == L'\\' && asFilePath[1] == L'\\' && asFilePath[2] == L'?' && asFilePath[3] == L'\\') + asFilePath += 4; + + // Если asFilePath содержит два (и более) ":\" + LPCWSTR pszColon = wcschr(asFilePath, L':'); + if (pszColon) + { + // Если есть ":", то это должен быть путь вида "X:\xxx", т.е. ":" - второй символ + if (pszColon != (asFilePath+1)) + return FALSE; + if (wcschr(pszColon+1, L':')) + return FALSE; + } + + // May be file path + return TRUE; +} + +BOOL FirstArg(LPCTSTR asCmdLine, TCHAR* rsArg/*[MAX_PATH+1]*/, LPCTSTR* rsNextArg) +{ + LPCTSTR psCmdLine = asCmdLine; + LPCTSTR pch = NULL; + TCHAR ch = *psCmdLine; + size_t nArgLen = 0; + + while (ch == _T(' ') || ch == _T('\t') || ch == _T('\r') || ch == _T('\n')) ch = *(++psCmdLine); + if (ch == 0) return FALSE; + + // аргумент начинается с " + if (ch == _T('"')) + { + psCmdLine++; + pch = wcschr(psCmdLine, _T('"')); + if (!pch) return FALSE; + while (pch[1] == _T('"')) + { + pch += 2; + pch = wcschr(pch, _T('"')); + if (!pch) return FALSE; + } + // Теперь в pch ссылка на последнюю " + } + else + { + // До конца строки или до первого пробела + //pch = wcschr(psCmdLine, _T(' ')); + // 09.06.2009 Maks - обломался на: cmd /c" echo Y " + pch = psCmdLine; + // Ищем обычным образом (до пробела/кавычки) + while (*pch && *pch!=_T(' ') && *pch!=_T('"')) pch++; + //if (!pch) pch = psCmdLine + lstrlenW(psCmdLine); // до конца строки + } + + nArgLen = pch - psCmdLine; + if (nArgLen > MAX_PATH) return FALSE; + + // Вернуть аргумент + memcpy(rsArg, psCmdLine, nArgLen*sizeof(TCHAR)); + rsArg[nArgLen] = 0; + + psCmdLine = pch; + + // Finalize + ch = *psCmdLine; // может указывать на закрывающую кавычку + if (ch == L'"') ch = *(++psCmdLine); + while (ch == L' ' || ch == L'\t' || ch == L'\r' || ch == L'\n') ch = *(++psCmdLine); + *rsNextArg = psCmdLine; + + return TRUE; +} + +int EntryMenu(int Sel, int& Action, bool& LowPriority, int nChkCount = 0) +{ +#ifdef FARAPI18 +#define SETITEM(i,s) items[i].Text = GetMsg(s) +#else +#define SETITEM(i,s) items[i].Text.TextPtr = GetMsg(s); items[i].Flags |= MIF_USETEXTPTR +#endif + FarMenuItemEx items[6]; memset(items, 0, sizeof(items)); + SETITEM(Action_UninstallWait, MActionUninstallWait); + SETITEM(Action_Uninstall, MActionUninstall); + if (nChkCount > 1) + items[Action_Uninstall].Flags |= MIF_DISABLE; + SETITEM(Action_ModifyWait, MActionModifyWait); + SETITEM(Action_Modify, MActionModify); + if (nChkCount > 1) + items[Action_Modify].Flags |= MIF_DISABLE; + else if (!p[Sel].CanModify) + { + items[Action_Modify].Flags |= MIF_DISABLE; + items[Action_ModifyWait].Flags |= MIF_DISABLE; + } + SETITEM(Action_RepairWait, MActionRepairWait); + SETITEM(Action_Repair, MActionRepair); + if (nChkCount > 1) + items[Action_Repair].Flags |= MIF_DISABLE; + else if (!p[Sel].CanRepair) + { + items[Action_Repair].Flags |= MIF_DISABLE; + items[Action_RepairWait].Flags |= MIF_DISABLE; + } + + int iRc; + int BreakCode; + int BreakKeys[2]={VK_F7,0}; + TCHAR szMenuTitle[MAX_PATH]; + + if (nChkCount > 1) + StringCchPrintf(szMenuTitle, ARRAYSIZE(szMenuTitle), GetMsg(MMenuTopLineN), nChkCount); + else + StringCchCopy(szMenuTitle, ARRAYSIZE(szMenuTitle), GetMsg(MMenuTopLine)); + + while (true) + { + iRc = Info.Menu(Info.ModuleNumber, -1,-1,0, FMENU_USEEXT|FMENU_WRAPMODE, szMenuTitle, + GetMsg(LowPriority ? MMenuBottomLine2 : MMenuBottomLine1), + _T("ActionMenu"), BreakKeys, &BreakCode, (struct FarMenuItem *)items, ARRAYSIZE(items)); + if (iRc < 0) + return -1; + if (BreakCode == 0) + { + LowPriority = !LowPriority; + for (UINT i = 0; i < ARRAYSIZE(items); i++) + { + if (i == iRc) + items[i].Flags |= MIF_SELECTED; + else + items[i].Flags &= ~MIF_SELECTED; + } + } + else + { + Action = iRc; + break; + } + } + + if ((Action & 0xFF) == Action_Menu) + return -1; // ошибка + + return Action; +} + +int ExecuteEntry(int Sel, int Action, bool LowPriority) +{ + if ((Action & 0xFF) == Action_Menu) + { + if (EntryMenu(Sel, Action, LowPriority) < 0) + return -1; + if ((Action & 0xFF) == Action_Menu) + return -1; // ошибка + } + + int nWaitSucceeded = 0; + STARTUPINFO si; + PROCESS_INFORMATION pi; + HANDLE hScreen; //for SaveScreen/RestoreScreen + + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); + + TCHAR cmd_line[MAX_PATH*2+1], cmd_file[MAX_PATH+1], cmd_parm[MAX_PATH*2+1]; + + LPCTSTR pszString = NULL; + + if ((Action == Action_ModifyWait) || (Action == Action_Modify)) + pszString = p[Sel].Keys[ModifyPath]; + //else if ((Action == Action_RepairWait) || (Action == Action_Repair)) + // pszString = NULL; + else if ((Action == Action_UninstallWait) || (Action == Action_Uninstall)) + { + if (!p[Sel].WindowsInstaller) + pszString = p[Sel].Keys[UninstallString]; + } + + if (pszString && !*pszString) + pszString = NULL; + + + if (p[Sel].WindowsInstaller && !(!Opt.ForceMsiUse && pszString)) + { + TCHAR szCode[6]; + if ((Action == Action_UninstallWait) || (Action == Action_Uninstall)) + StringCchCopy(szCode, ARRAYSIZE(szCode), _T(" /x ")); + else if ((Action == Action_RepairWait) || (Action == Action_Repair)) + StringCchCopy(szCode, ARRAYSIZE(szCode), _T(" /fa ")); + else //if ((Action == Action_ModifyWait) || (Action == Action_Modify)) + StringCchCopy(szCode, ARRAYSIZE(szCode), _T(" /i ")); + // Для CreateProcess + StringCchCopy(cmd_line, ARRAYSIZE(cmd_line), _T("msiexec")); + StringCchCat(cmd_line, ARRAYSIZE(cmd_line), szCode); + StringCchCat(cmd_line, ARRAYSIZE(cmd_line), p[Sel].SubKeyName); + // Для ShellExecuteEx + if (LowPriority) + { + StringCchCopy(cmd_file, ARRAYSIZE(cmd_parm), _T("cmd")); + StringCchCopy(cmd_parm, ARRAYSIZE(cmd_parm), _T("/c start /low ")); + StringCchCat(cmd_parm, ARRAYSIZE(cmd_parm), _T("msiexec")); + StringCchCat(cmd_parm, ARRAYSIZE(cmd_parm), szCode); + StringCchCat(cmd_parm, ARRAYSIZE(cmd_parm), p[Sel].SubKeyName); + } + else + { + StringCchCopy(cmd_file, ARRAYSIZE(cmd_file), _T("msiexec")); + StringCchCopy(cmd_parm, ARRAYSIZE(cmd_parm), szCode); + StringCchCat(cmd_parm, ARRAYSIZE(cmd_parm), p[Sel].SubKeyName); + } + } + else + { + if (pszString == NULL) + return 0; + // Для CreateProcess + StringCchCopy(cmd_line, ARRAYSIZE(cmd_line), pszString); + // Для ShellExecuteEx + if (LowPriority) + { + StringCchCopy(cmd_file, ARRAYSIZE(cmd_parm), _T("cmd")); + StringCchCopy(cmd_parm, ARRAYSIZE(cmd_parm), _T("/c start /low \"\" ")); + StringCchCat(cmd_parm, ARRAYSIZE(cmd_parm), pszString); + } + else + { + LPCTSTR psNextArg = NULL; + if (FirstArg(pszString, cmd_file, &psNextArg) + && IsFilePath(cmd_file)) + { + StringCchCopy(cmd_parm, ARRAYSIZE(cmd_parm), psNextArg); + } + else + { + StringCchCopy(cmd_file, ARRAYSIZE(cmd_file), pszString); + cmd_parm[0] = 0; + } + } + } + + hScreen = Info.SaveScreen(0,0,-1,-1); //Это необходимо сделать, т.к. после запущенных программ нужно обновить окно ФАРа + + BOOL ifCreate = FALSE, bElevationFailed = FALSE, bPriorityChanged = FALSE; + DWORD dwErr = 0; + + // MSI сам выполнит повышение прав когда потребуется + if (!p[Sel].WindowsInstaller && Opt.UseElevation && !IsUserAdmin()) + { + // Required elevation + SHELLEXECUTEINFO sei = {sizeof(SHELLEXECUTEINFO)}; + sei.fMask = SEE_MASK_NOCLOSEPROCESS; + sei.lpVerb = _T("runas"); + sei.lpFile = cmd_file; + sei.lpParameters = cmd_parm; + sei.nShow = LowPriority ? SW_MINIMIZE : SW_SHOWNORMAL; + ifCreate = ShellExecuteEx(&sei); + if (ifCreate) + pi.hProcess = sei.hProcess; + else + bElevationFailed = true; + } + + // Если Elevation не запускался + if (!ifCreate) + { + ifCreate = CreateProcess // Start the child process. + ( + NULL, // No module name (use command line). + cmd_line, // Command line. + NULL, // Process handle not inheritable. + NULL, // Thread handle not inheritable. + FALSE, // Set handle inheritance to FALSE. + LowPriority ? IDLE_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS, // Creation flags. + NULL, // Use parent's environment block. + NULL, // Use parent's starting directory. + &si, // Pointer to STARTUPINFO structure. + &pi // Pointer to PROCESS_INFORMATION structure. + ); + if (ifCreate) + bPriorityChanged = TRUE; + } + + if (!ifCreate) //not Create + { + dwErr = GetLastError(); + if ((dwErr == 0x2E4) && !bElevationFailed) + { + // Required elevation + SHELLEXECUTEINFO sei = {sizeof(SHELLEXECUTEINFO)}; + sei.fMask = SEE_MASK_NOCLOSEPROCESS; + sei.lpVerb = _T("runas"); + sei.lpFile = cmd_file; + sei.lpParameters = cmd_parm; + sei.nShow = LowPriority ? SW_MINIMIZE : SW_SHOWNORMAL; + ifCreate = ShellExecuteEx(&sei); + if (ifCreate) + pi.hProcess = sei.hProcess; + else + dwErr = GetLastError(); + } + if (!ifCreate) //not Create + { + TCHAR szErrCode[32]; + const TCHAR *pszErrInfo = szErrCode; + if (dwErr == 0x000004C7) + pszErrInfo = GetMsg(MCancelledByUser); + else + StringCchPrintf(szErrCode, ARRAYSIZE(szErrCode), _T("ErrorCode=0x%08X"), dwErr); + if (hScreen) + Info.RestoreScreen(hScreen); + DrawMessage(FMSG_WARNING, 1, "%s",GetMsg(MPlugIn),GetMsg(MRunProgErr),cmd_line,pszErrInfo,GetMsg(MBtnOk),NULL); + return -1; + } + } + + // -- не может, если был сделан Elevation, а если Elevation не было - то уже в CreateProcess + //if (pi.hProcess && LowPriority && !bPriorityChanged) + //{ + // bPriorityChanged = SetPriorityClass(pi.hProcess, IDLE_PRIORITY_CLASS); + // dwErr = GetLastError(); + //} + + TCHAR SaveTitle[MAX_PATH]; + GetConsoleTitle(SaveTitle,ARRAYSIZE(SaveTitle)); + SaveTitle[ARRAYSIZE(SaveTitle) - 1] = 0; + SetConsoleTitle(cmd_line); + + if (pi.hProcess) + { + // Wait until child process exits. + if ((Action == Action_UninstallWait) + || (Action == Action_ModifyWait) + || (Action == Action_RepairWait)) + { + DrawMessage(0, 0, "%s", GetMsg(MPlugIn), GetMsg(MWaitingCompletion), cmd_line,NULL); + nWaitSucceeded = 1; + while (true) + { + if (WaitForSingleObject(pi.hProcess, 500) == WAIT_OBJECT_0) + break; + if (CheckForEsc()) + { + nWaitSucceeded = 0; + break; + } + } + } + // Close process and thread handles. + CloseHandle(pi.hProcess); + } + if (pi.hThread) + CloseHandle(pi.hThread); + + SetConsoleTitle(SaveTitle); + + if (hScreen) + { + Info.RestoreScreen(NULL); + Info.RestoreScreen(hScreen); + } + return nWaitSucceeded; +} + +typedef WINADVAPI LSTATUS (APIENTRY *FRegDeleteKeyExA)(__in HKEY hKey, __in LPCSTR lpSubKey, __in REGSAM samDesired, __reserved DWORD Reserved); +typedef WINADVAPI LSTATUS (APIENTRY *FRegDeleteKeyExW)(__in HKEY hKey, __in LPCWSTR lpSubKey, __in REGSAM samDesired, __reserved DWORD Reserved); + +bool DeleteEntry(int Sel) +{ + HMODULE h_mod = LoadLibrary(_T("advapi32.dll")); + FRegDeleteKeyExA RegDeleteKeyExA = reinterpret_cast(GetProcAddress(h_mod, "RegDeleteKeyExA")); + FRegDeleteKeyExW RegDeleteKeyExW = reinterpret_cast(GetProcAddress(h_mod, "RegDeleteKeyExW")); + FreeLibrary(h_mod); + + HKEY userKey; + LONG ret = RegOpenKeyEx(p[Sel].RegKey.Root, p[Sel].RegKey.Path, 0, DELETE | p[Sel].RegView, &userKey); + if (ret != ERROR_SUCCESS) return false; + if (RegDeleteKeyEx) + ret = RegDeleteKeyEx(userKey, p[Sel].SubKeyName, p[Sel].RegView, 0); + else + ret = RegDeleteKey(userKey, p[Sel].SubKeyName); + RegCloseKey(userKey); + if (ret != ERROR_SUCCESS) return false; + return true; +} + +//сравнить строки +int __cdecl CompareEntries(const void* item1, const void* item2) +{ + return FSF.LStricmp(reinterpret_cast(item1)->Keys[DisplayName], reinterpret_cast(item2)->Keys[DisplayName]); +} +//сравнить даты +int __cdecl CompareEntriesDate(const void* item1, const void* item2) +{ + if (reinterpret_cast(item1)->InstDateN < reinterpret_cast(item2)->InstDateN) + return 1; + if (reinterpret_cast(item1)->InstDateN > reinterpret_cast(item2)->InstDateN) + return -1; + return CompareEntries(item1, item2); +} + +#define JUMPREALLOC 50 +void EnumKeys(RegKeyPath& RegKey, REGSAM RegView = 0) { + HKEY hKey; + if (RegOpenKeyEx(RegKey.Root, RegKey.Path, 0, KEY_READ | RegView, &hKey) != ERROR_SUCCESS) + return; + DWORD cSubKeys; + if (RegQueryInfoKey(hKey,NULL,NULL,NULL,&cSubKeys,NULL,NULL,NULL,NULL,NULL,NULL,NULL) != ERROR_SUCCESS) + return; + + TCHAR Buf[MAX_PATH]; + for (DWORD fEnumIndex=0; fEnumIndex= nRealCount) + { + nRealCount += JUMPREALLOC; + p = (KeyInfo *) realloc(p, sizeof(KeyInfo) * nRealCount); + } + if (FillReg(p[nCount], Buf, RegKey, RegView)) + { +#ifdef FARAPI17 + CharToOem(p[nCount].Keys[DisplayName], p[nCount].Keys[DisplayName]); + CharToOem(p[nCount].Keys[UninstallString], p[nCount].Keys[UninstallString]); + CharToOem(p[nCount].Keys[ModifyPath], p[nCount].Keys[ModifyPath]); +#endif + nCount++; + } + } + RegCloseKey(hKey); +} +#undef JUMPREALLOC + +typedef WINBASEAPI VOID (WINAPI *FGetNativeSystemInfo)(__out LPSYSTEM_INFO lpSystemInfo); + +#define EMPTYSTR _T(" ") +//Обновление информации +void UpDateInfo(void) +{ + HMODULE h_mod = LoadLibrary(_T("kernel32.dll")); + FGetNativeSystemInfo GetNativeSystemInfo = reinterpret_cast(GetProcAddress(h_mod, "GetNativeSystemInfo")); + FreeLibrary(h_mod); + bool is_os_x64 = false; + if (GetNativeSystemInfo) + { + SYSTEM_INFO si; + GetNativeSystemInfo(&si); + is_os_x64 = si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64; + } + + nCount = nRealCount = 0; + for (int i=0;i(FLI[i].Text); + + if (FirstChar[1] != FSF.LUpper(p[i].Keys[DisplayName][0])) + { + FirstChar[1] = FSF.LUpper(p[i].Keys[DisplayName][0]); + StringCchCopy(text, MaxSize, FirstChar); + } + else + StringCchCopy(text, MaxSize, EMPTYSTR); + + if (p[i].RegKey.Root == HKEY_LOCAL_MACHINE) + { + if (is_os_x64) + StringCchCat(text, MaxSize, (p[i].RegView == KEY_WOW64_64KEY) ? sx64 : sx86); + else + StringCchCat(text, MaxSize, sHKLM); + } + else + StringCchCat(text, MaxSize, sHKCU); + + StringCchCat(text, MaxSize, _T(" ")); + StringCchCat(text, MaxSize, p[i].InstDate); + StringCchCat(text, MaxSize, _T(" ")); + StringCchCat(text, MaxSize, (p[i].WindowsInstaller) ? _T("W") : _T(" ")); + StringCchCat(text, MaxSize, (p[i].CanModify) ? _T("M") : _T(" ")); + StringCchCat(text, MaxSize, (p[i].CanRepair) ? _T("R") : _T(" ")); + StringCchCat(text, MaxSize, (p[i].Hidden) ? _T("-") : _T(" ")); + StringCchCat(text, MaxSize, _T(" ")); + + //if ((p[i].Keys[ModifyPath][0] == 0) && (p[i].Keys[UninstallString][0] == 0)) + //if (p[i].Hidden) + // StringCchCat(text, MaxSize, _T(" - ")); + //else + // StringCchCat(text, MaxSize, _T(" ")); + + size_t nCurLen = _tcslen(text); + //StringCchCat(text, MaxSize, p[i].Keys[DisplayName]); + StringCchCopyN(text+nCurLen, MaxSize-nCurLen, p[i].Keys[DisplayName], MaxSize-nCurLen-1); + text[MaxSize-1] = 0; + } + + ListSize = nCount; +} +#undef EMPTYSTR + +//------------------------------------------------------------------- + +void ReadRegistry() +{ + //TechInfo + if (GetRegKey(HKCU,_T(""),_T("WhereWork"),Opt.WhereWork,3)) + if ((Opt.WhereWork<0) || (Opt.WhereWork>3)) + Opt.WhereWork=3; + SetRegKey(HKCU,_T(""),_T("WhereWork"),(DWORD) Opt.WhereWork); + + if (GetRegKey(HKCU,_T(""),_T("EnterAction"),Opt.EnterAction,Action_Menu)) + if ((Opt.EnterAction<0) || (Opt.EnterAction>Action_Menu)) + Opt.EnterAction = Action_Menu; + SetRegKey(HKCU,_T(""),_T("EnterAction"),(DWORD) Opt.EnterAction); + + if (GetRegKey(HKCU,_T(""),_T("ShiftEnterAction"),Opt.ShiftEnterAction,Action_UninstallWait)) + if ((Opt.ShiftEnterAction<0) || (Opt.ShiftEnterAction>Action_Menu)) + Opt.ShiftEnterAction = Action_Menu; + SetRegKey(HKCU,_T(""),_T("ShiftEnterAction"),(DWORD) Opt.ShiftEnterAction); + + if (GetRegKey(HKCU,_T(""),_T("UseElevation"),Opt.UseElevation,1)) + if ((Opt.UseElevation<0) || (Opt.UseElevation>1)) + Opt.UseElevation=1; + SetRegKey(HKCU,_T(""),_T("UseElevation"),(DWORD) Opt.UseElevation); + + if (GetRegKey(HKCU,_T(""),_T("RunLowPriority"),Opt.RunLowPriority,0)) + if ((Opt.RunLowPriority<0) || (Opt.RunLowPriority>1)) + Opt.RunLowPriority=0; + SetRegKey(HKCU,_T(""),_T("RunLowPriority"),(DWORD) Opt.RunLowPriority); + + if (GetRegKey(HKCU,_T(""),_T("ForceMsiUse"),Opt.ForceMsiUse,0)) + if ((Opt.ForceMsiUse<0) || (Opt.ForceMsiUse>1)) + Opt.ForceMsiUse=0; + SetRegKey(HKCU,_T(""),_T("ForceMsiUse"),(DWORD) Opt.ForceMsiUse); + + Opt.SortByDate = false; +} diff --git a/Uninstall/src/UnInstall.vcproj b/Uninstall/src/UnInstall.vcproj index 3ef7de0..0484c3d 100644 --- a/Uninstall/src/UnInstall.vcproj +++ b/Uninstall/src/UnInstall.vcproj @@ -61,7 +61,7 @@ /> +struct DialogItemBinding +{ + int BeforeLabelID; + int AfterLabelID; + + DialogItemBinding() + : BeforeLabelID(-1), AfterLabelID(-1) + { + } + + virtual void SaveValue(T *Item, int RadioGroupIndex) + { + } +}; + +template +struct CheckBoxBinding: public DialogItemBinding +{ + private: + BOOL *Value; + int Mask; + + public: + CheckBoxBinding(BOOL *aValue, int aMask) : Value(aValue), Mask(aMask) { } + + virtual void SaveValue(T *Item, int RadioGroupIndex) + { + if (Mask == 0) + { + *Value = Item->Selected; + } + else + { + if (Item->Selected) + *Value |= Mask; + else + *Value &= ~Mask; + } + } +}; + +template +struct RadioButtonBinding: public DialogItemBinding +{ + private: + int *Value; + + public: + RadioButtonBinding(int *aValue) : Value(aValue) { } + + virtual void SaveValue(T *Item, int RadioGroupIndex) + { + if (Item->Selected) + *Value = RadioGroupIndex; + } +}; + +template +struct ComboBoxBinding: public DialogItemBinding +{ + int *Value; + FarList *List; + + ComboBoxBinding(int *aValue, FarList *aList) + : Value(aValue), List(aList) + { + } + + ~ComboBoxBinding() + { + delete [] List->Items; + delete List; + } + + virtual void SaveValue(T *Item, int RadioGroupIndex) + { + FarListItem &ListItem = List->Items[Item->ListPos]; + *Value = ListItem.Reserved[0]; + } +}; + +/* +Класс для динамического построения диалогов. Автоматически вычисляет положение и размер +для добавляемых контролов, а также размер самого диалога. Автоматически записывает выбранные +значения в указанное место после закрытия диалога по OK. + +По умолчанию каждый контрол размещается в новой строке диалога. Ширина для текстовых строк, +checkbox и radio button вычисляется автоматически, для других элементов передаётся явно. +Есть также возможность добавить статический текст слева или справа от контрола, при помощи +методов AddTextBefore и AddTextAfter. + +Поддерживается также возможность расположения контролов в две колонки. Используется следующим +образом: +- StartColumns() +- добавляются контролы для первой колонки +- ColumnBreak() +- добавляются контролы для второй колонки +- EndColumns() + +Базовая версия класса используется как внутри кода FAR, так и в плагинах. +*/ + +template +class DialogBuilderBase +{ + protected: + T *DialogItems; + DialogItemBinding **Bindings; + int DialogItemsCount; + int DialogItemsAllocated; + int NextY; + int OKButtonID, CancelButtonID; + int ColumnStartIndex; + int ColumnBreakIndex; + int ColumnStartY; + int ColumnEndY; + int ColumnMinWidth; + + static const int SECOND_COLUMN = -2; + static const int RIGHT_SLIDE = -3; + + void ReallocDialogItems() + { + // реаллокация инвалидирует указатели на DialogItemEx, возвращённые из + // AddDialogItem и аналогичных методов, поэтому размер массива подбираем такой, + // чтобы все нормальные диалоги помещались без реаллокации + // TODO хорошо бы, чтобы они вообще не инвалидировались + DialogItemsAllocated += 128; + if (DialogItems == nullptr) + { + DialogItems = new T[DialogItemsAllocated]; + Bindings = new DialogItemBinding * [DialogItemsAllocated]; + } + else + { + T *NewDialogItems = new T[DialogItemsAllocated]; + DialogItemBinding **NewBindings = new DialogItemBinding * [DialogItemsAllocated]; + for(int i=0; iType = Type; + Bindings [Index] = nullptr; + return Item; + } + +public: + void SetNextY(T *Item) + { + Item->X1 = 5; + Item->Y1 = Item->Y2 = NextY++; + } + + void SlideItemUp(T *Item) + { + int Width = Item->X2 - Item->X1; + Item->X1 = RIGHT_SLIDE; + Item->X2 = Item->X1 + Width; + NextY--; + Item->Y1 = Item->Y2 = NextY - 1; + } + + int ItemWidth(const T &Item) + { + switch(Item.Type) + { + case DI_TEXT: + return TextWidth(Item); + + case DI_CHECKBOX: + case DI_RADIOBUTTON: + return TextWidth(Item) + 4; + + case DI_EDIT: + case DI_FIXEDIT: + case DI_COMBOBOX: + int Width = Item.X2 - Item.X1 + 1; + /* стрелка history занимает дополнительное место, но раньше она рисовалась поверх рамки + if (Item.Flags & DIF_HISTORY) + Width++; + */ + return Width; + break; + } + return 0; + } + + void AddBorder(const TCHAR *TitleText) + { + T *Title = AddDialogItem(DI_DOUBLEBOX, TitleText); + Title->X1 = 3; + Title->Y1 = 1; + } + + void UpdateBorderSize() + { + T *Title = &DialogItems[0]; + Title->X2 = Title->X1 + MaxTextWidth() + 3; + Title->Y2 = DialogItems [DialogItemsCount-1].Y2 + 1; + } + + int MaxTextWidth() + { + int MaxWidth = 0; + for(int i=1; i *Binding = FindBinding(DialogItems+i); + int BeforeWidth = 0; + if (Binding && Binding->BeforeLabelID != -1) { + BeforeWidth = DialogItems [Binding->BeforeLabelID].X2 - DialogItems [Binding->BeforeLabelID].X1 + 1; + } + + int Width = DialogItems [i].X2 - DialogItems [i].X1; + DialogItems [i].X1 = SecondColumnX1 + BeforeWidth; + DialogItems [i].X2 = DialogItems [i].X1 + Width; + + if (Binding && Binding->AfterLabelID != -1) + { + int j = Binding->AfterLabelID; + int AfterWidth = DialogItems [j].X2 - DialogItems [j].X1; + if (DialogItems [j].X1 == SECOND_COLUMN) + { + DialogItems [j].X1 = SecondColumnX1 + Width + 2; + DialogItems [j].X2 = DialogItems [j].X1 + AfterWidth; + } + else + { + DialogItems [j].X1 += Width + 2; + DialogItems [j].X2 += Width + 2; + } + } + } + } + } + + void UpdateRightSlidePosition() + { + int SlideX2 = DialogItems [0].X2 - 2; + for(int i=0; i *Binding) + { + Bindings [DialogItemsCount-1] = Binding; + } + + int GetItemID(T *Item) + { + int Index = static_cast(Item - DialogItems); + if (Index >= 0 && Index < DialogItemsCount) + return Index; + return -1; + } + + DialogItemBinding* FindBinding(const T *Item) + { + int Index = static_cast(Item - DialogItems); + if (Index >= 0 && Index < DialogItemsCount) + return Bindings [Index]; + return nullptr; + } + + void SaveValues() + { + int RadioGroupIndex = 0; + for(int i=0; iSaveValue(&DialogItems [i], RadioGroupIndex); + } + } + + virtual const TCHAR* GetLangString(int MessageID) + { + return nullptr; + } + + virtual int DoShowDialog() + { + return -1; + } + + virtual DialogItemBinding* CreateCheckBoxBinding(BOOL *Value, int Mask) + { + return nullptr; + } + + virtual DialogItemBinding* CreateComboBoxBinding(int *Value) + { + return nullptr; + } + + virtual DialogItemBinding* CreateRadioButtonBinding(int *Value) + { + return nullptr; + } + + DialogBuilderBase() + : DialogItems(nullptr), DialogItemsCount(0), DialogItemsAllocated(0), NextY(2), + ColumnStartIndex(-1), ColumnBreakIndex(-1), ColumnMinWidth(0) + { + } + + ~DialogBuilderBase() + { + for(int i=0; iFlags |= DIF_CENTERTEXT; + // Item->X2 = Item->X1 + ItemWidth(*Item); + //} + + // Добавляет чекбокс. + T* AddCheckbox(int TextMessageId, BOOL *Value, int Mask=0) + { + T *Item = AddDialogItem(DI_CHECKBOX, GetLangString(TextMessageId)); + SetNextY(Item); + Item->X2 = Item->X1 + ItemWidth(*Item); + if (Mask == 0) + Item->Selected = *Value; + else + Item->Selected = (*Value & Mask) != 0; + SetLastItemBinding(CreateCheckBoxBinding(Value, Mask)); + return Item; + } + + // Добавляет группу радиокнопок. + int AddRadioButtons(int *Value, int OptionCount, int MessageIDs[], DWORD AddFlags=0, BOOL abTwoColumns = FALSE) + { + if (abTwoColumns && (ColumnStartIndex != -1 || OptionCount < 2)) + abTwoColumns = FALSE; + if (abTwoColumns) + StartColumns(); + + int nBreakColumn = abTwoColumns ? (((OptionCount+1)>>1)-1) : (OptionCount+1); + int nFirstID = DialogItemsCount; + for(int i=0; iX2 = Item->X1 + ItemWidth(*Item); + if (i == 0) + Item->Flags |= DIF_GROUP; + if (*Value == i) + Item->Selected = TRUE; + if (AddFlags) + Item->Flags |= AddFlags; + SetLastItemBinding(CreateRadioButtonBinding(Value)); + if (i == nBreakColumn) + ColumnBreak(); + } + if (abTwoColumns) + EndColumns(); + return nFirstID; + } + + // Добавляет ComboBox + T* AddComboBox(int Width, FarList* ListItems, int *Value, DWORD AddFlags=DIF_DROPDOWNLIST) + { + T *Item = AddDialogItem(DI_COMBOBOX, nullptr); + for (int i = 0; i < ListItems->ItemsNumber; i++) + { + if (i == *Value) + ListItems->Items[i].Flags |= LIF_SELECTED; + else if (ListItems->Items[i].Flags & LIF_SELECTED) + ListItems->Items[i].Flags &= ~LIF_SELECTED; + } + Item->ListItems = ListItems; + Item->Flags |= AddFlags; + SetNextY(Item); + Item->X2 = Item->X1 + Width; + SetLastItemBinding(CreateComboBoxBinding(Value)); + return Item; + } + + // Добавляет поле типа DI_FIXEDIT для редактирования указанного числового значения. + virtual T* AddIntEditField(int *Value, int Width) + { + return nullptr; + } + + // Добавляет указанную текстовую строку слева от элемента RelativeTo. + T* AddTextBefore(T *RelativeTo, int LabelId) + { + T *Item = AddDialogItem(DI_TEXT, GetLangString(LabelId)); + Item->Y1 = Item->Y2 = RelativeTo->Y1; + Item->X1 = 5; + Item->X2 = Item->X1 + ItemWidth(*Item) - 1; + + int RelativeToWidth = RelativeTo->X2 - RelativeTo->X1; + RelativeTo->X1 = Item->X2 + 2; + RelativeTo->X2 = RelativeTo->X1 + RelativeToWidth; + + //// Текст должен идти первым элементом, чтобы хоткеи срабатывали + //T P; P = *RelativeTo; *RelativeTo = *Item; *Item = P; + //Item--; RelativeTo++; + + //int I1 = static_cast(Item - DialogItems); + //int I2 = static_cast(RelativeTo - DialogItems); + //DialogItemBinding *B1; + //B1 = Bindings[I1]; Bindings[I1] = Bindings[I2]; Bindings[I2] = B1; + + DialogItemBinding *Binding = FindBinding(RelativeTo); + if (Binding) + Binding->BeforeLabelID = GetItemID(Item); + + return Item; + } + + // Подвязать (a'la AddTextAfter) любой элемент к любому элементу + void MoveItemAfter(T *FirstItem, T *AfterItem) + { + int Width = ItemWidth(*AfterItem); + int Height = AfterItem->Y2 - AfterItem->Y1; + + AfterItem->Y1 = FirstItem->Y1; + AfterItem->Y2 = FirstItem->Y1 + Height; + AfterItem->X1 = FirstItem->X1 + ItemWidth(*FirstItem); + AfterItem->X2 = AfterItem->X1 + Width - 1; + + DialogItemBinding *Binding = FindBinding(AfterItem); + if (Binding) + { + Binding->BeforeLabelID = GetItemID(FirstItem); + _ASSERTE(Binding->BeforeLabelID != -1); + } + + NextY--; + } + + // Добавляет указанную текстовую строку справа от элемента RelativeTo. + T* AddTextAfter(T *RelativeTo, int LabelId) + { + T *Item = AddDialogItem(DI_TEXT, GetLangString(LabelId)); + Item->Y1 = Item->Y2 = RelativeTo->Y1; + Item->X1 = RelativeTo->X2 + 2; + + DialogItemBinding *Binding = FindBinding(RelativeTo); + if (Binding) + Binding->AfterLabelID = GetItemID(Item); + + return Item; + } + + // Начинает располагать поля диалога в две колонки. + void StartColumns() + { + ColumnStartIndex = DialogItemsCount; + ColumnStartY = NextY; + } + + // Завершает колонку полей в диалоге и переходит к следующей колонке. + void ColumnBreak() + { + ColumnBreakIndex = DialogItemsCount; + ColumnEndY = NextY; + NextY = ColumnStartY; + } + + // Завершает расположение полей диалога в две колонки. + void EndColumns() + { + for(int i=ColumnStartIndex; i *Binding = FindBinding(DialogItems + i); + int BindingAdd = 0; + if (Binding) { + if (Binding->BeforeLabelID != -1) + BindingAdd = ItemWidth(DialogItems [Binding->BeforeLabelID]) + 1; + else if (Binding->AfterLabelID != -1) + BindingAdd = ItemWidth(DialogItems [Binding->AfterLabelID]) + 1; + } + + if ((Width + BindingAdd) > ColumnMinWidth) + ColumnMinWidth = Width + BindingAdd; + if (i >= ColumnBreakIndex) + { + DialogItems [i].X1 = SECOND_COLUMN; + DialogItems [i].X2 = SECOND_COLUMN + Width; + } + } + + if (ColumnEndY > NextY) + NextY = ColumnEndY; + + ColumnStartIndex = -1; + ColumnBreakIndex = -1; + } + + // Добавляет пустую строку. + void AddEmptyLine() + { + NextY++; + } + + // Добавляет сепаратор. + void AddSeparator(int MessageId=-1) + { + T *Separator = AddDialogItem(DI_TEXT, MessageId == -1 ? EMPTY_TEXT : GetLangString(MessageId)); + Separator->Flags = DIF_SEPARATOR; + Separator->X1 = 3; + Separator->Y1 = Separator->Y2 = NextY++; + } + + // Добавляет сепаратор, кнопки OK и Cancel. + void AddOKCancel(int OKMessageId, int CancelMessageId) + { + AddSeparator(); + + T *OKButton = AddDialogItem(DI_BUTTON, GetLangString(OKMessageId)); + OKButton->Flags = DIF_CENTERGROUP; + OKButton->DefaultButton = TRUE; + OKButton->Y1 = OKButton->Y2 = NextY++; + OKButtonID = DialogItemsCount-1; + + T *CancelButton = AddDialogItem(DI_BUTTON, GetLangString(CancelMessageId)); + CancelButton->Flags = DIF_CENTERGROUP; + CancelButton->Y1 = CancelButton->Y2 = OKButton->Y1; + CancelButtonID = DialogItemsCount-1; + } + + void AddFooterButtons(int* BtnID, int nBtnCount) + { + AddSeparator(); + + for (int i = 0; i < nBtnCount; i++) + { + T *Button = AddDialogItem(DI_BUTTON, GetLangString(BtnID[i])); + Button->Flags = DIF_CENTERGROUP; + Button->DefaultButton = TRUE; + Button->Y1 = Button->Y2 = NextY; + if (i == 0) + OKButtonID = DialogItemsCount-1; + } + CancelButtonID = DialogItemsCount-1; + + NextY++; + } + + bool ShowDialog(int *pnBtnNo = NULL) + { + _ASSERTE(OKButtonID > 0 && OKButtonID < DialogItemsCount); + UpdateBorderSize(); + UpdateSecondColumnPosition(); + UpdateRightSlidePosition(); + int Result = DoShowDialog(); + if (Result >= OKButtonID && Result < CancelButtonID) + { + SaveValues(); + if (pnBtnNo) *pnBtnNo = (Result - OKButtonID); + return true; + } + return false; + } +}; + +class PluginDialogBuilder; + +class DialogAPIBinding: public DialogItemBinding +{ +protected: + const PluginStartupInfo &Info; + HANDLE *DialogHandle; + int ID; + + DialogAPIBinding(const PluginStartupInfo &aInfo, HANDLE *aHandle, int aID) + : Info(aInfo), DialogHandle(aHandle), ID(aID) + { + } +}; + +class PluginCheckBoxBinding: public DialogAPIBinding +{ + BOOL *Value; + int Mask; + +public: + PluginCheckBoxBinding(const PluginStartupInfo &aInfo, HANDLE *aHandle, int aID, BOOL *aValue, int aMask) + : DialogAPIBinding(aInfo, aHandle, aID), + Value(aValue), Mask(aMask) + { + } + + virtual void SaveValue(FarDialogItem *Item, int RadioGroupIndex) + { + BOOL Selected = static_cast(Info.SendDlgMessage(*DialogHandle, DM_GETCHECK, ID, 0)); + if (Mask == 0) + { + *Value = Selected; + } + else + { + if (Selected) + *Value |= Mask; + else + *Value &= ~Mask; + } + } +}; + +class PluginRadioButtonBinding: public DialogAPIBinding +{ + private: + int *Value; + + public: + PluginRadioButtonBinding(const PluginStartupInfo &aInfo, HANDLE *aHandle, int aID, int *aValue) + : DialogAPIBinding(aInfo, aHandle, aID), + Value(aValue) + { + } + + virtual void SaveValue(FarDialogItem *Item, int RadioGroupIndex) + { + if (Info.SendDlgMessage(*DialogHandle, DM_GETCHECK, ID, 0)) + *Value = RadioGroupIndex; + } +}; + +class PluginComboBoxBinding: public DialogAPIBinding +{ + private: + int *Value; + + public: + PluginComboBoxBinding(const PluginStartupInfo &aInfo, HANDLE *aHandle, int aID, int *aValue) + : DialogAPIBinding(aInfo, aHandle, aID), + Value(aValue) + { + } + + virtual void SaveValue(FarDialogItem *Item, int RadioGroupIndex) + { + *Value = (int)Info.SendDlgMessage(*DialogHandle, DM_LISTGETCURPOS, ID, 0); + } +}; + +#ifdef UNICODE + +class PluginEditFieldBinding: public DialogAPIBinding +{ +private: + TCHAR *Value; + int MaxSize; + +public: + PluginEditFieldBinding(const PluginStartupInfo &aInfo, HANDLE *aHandle, int aID, TCHAR *aValue, int aMaxSize) + : DialogAPIBinding(aInfo, aHandle, aID), Value(aValue), MaxSize(aMaxSize) + { + } + + virtual void SaveValue(FarDialogItem *Item, int RadioGroupIndex) + { + const TCHAR *DataPtr = (const TCHAR *) Info.SendDlgMessage(*DialogHandle, DM_GETCONSTTEXTPTR, ID, 0); + lstrcpyn(Value, DataPtr, MaxSize); + } +}; + +class PluginIntEditFieldBinding: public DialogAPIBinding +{ +private: + int *Value; + TCHAR Buffer[32]; + TCHAR Mask[32]; + +public: + PluginIntEditFieldBinding(const PluginStartupInfo &aInfo, HANDLE *aHandle, int aID, int *aValue, int Width) + : DialogAPIBinding(aInfo, aHandle, aID), + Value(aValue) + { + aInfo.FSF->itoa(*aValue, Buffer, 10); + int MaskWidth = Width < 31 ? Width : 31; + for(int i=0; iatoi(DataPtr); + } + + TCHAR* GetBuffer() + { + return Buffer; + } + + const TCHAR* GetMask() + { + return Mask; + } +}; + +#else + +class PluginEditFieldBinding: public DialogItemBinding +{ +private: + TCHAR *Value; + int MaxSize; + +public: + PluginEditFieldBinding(TCHAR *aValue, int aMaxSize) + : Value(aValue), MaxSize(aMaxSize) + { + } + + virtual void SaveValue(FarDialogItem *Item, int RadioGroupIndex) + { + lstrcpyn(Value, Item->Data, MaxSize); + } +}; + +class PluginIntEditFieldBinding: public DialogItemBinding +{ +private: + const PluginStartupInfo &Info; + int *Value; + TCHAR Mask[32]; + +public: + PluginIntEditFieldBinding(const PluginStartupInfo &aInfo, int *aValue, int Width) + : Info(aInfo), Value(aValue) + { + int MaskWidth = Width < 31 ? Width : 31; + for(int i=0; iatoi(Item->Data); + } + + const TCHAR* GetMask() + { + return Mask; + } +}; + +#endif + +/* +Версия класса для динамического построения диалогов, используемая в плагинах к FAR. +*/ +class PluginDialogBuilder: public DialogBuilderBase +{ + public: + DWORD DialogFlags; + protected: + const PluginStartupInfo &Info; + HANDLE DialogHandle; + const TCHAR *HelpTopic; + + virtual void InitDialogItem(FarDialogItem *Item, const TCHAR *Text) + { + memset(Item, 0, sizeof(FarDialogItem)); + if (Text) + { + #ifdef UNICODE + Item->PtrData = Text; + #else + lstrcpyn(Item->Data, Text, sizeof(Item->Data)/sizeof(Item->Data[0])); + #endif + } + } + + virtual int TextWidth(const FarDialogItem &Item) + { +#ifdef UNICODE + return lstrlen(Item.PtrData); +#else + return lstrlen(Item.Data); +#endif + } + + virtual const TCHAR* GetLangString(int MessageID) + { + return Info.GetMsg(Info.ModuleNumber, MessageID); + } + + virtual int DoShowDialog() + { + int Width = DialogItems [0].X2+4; + int Height = DialogItems [0].Y2+2; +#ifdef UNICODE + DialogHandle = Info.DialogInit(Info.ModuleNumber, -1, -1, Width, Height, + HelpTopic, DialogItems, DialogItemsCount, 0, DialogFlags, nullptr, 0); + return Info.DialogRun(DialogHandle); +#else + return Info.DialogEx(Info.ModuleNumber, -1, -1, Width, Height, + HelpTopic, DialogItems, DialogItemsCount, 0, DialogFlags, nullptr, 0); +#endif + } + + virtual DialogItemBinding* CreateCheckBoxBinding(BOOL *Value, int Mask) + { +#ifdef UNICODE + return new PluginCheckBoxBinding(Info, &DialogHandle, DialogItemsCount-1, Value, Mask); +#else + return new CheckBoxBinding(Value, Mask); +#endif + } + + virtual DialogItemBinding* CreateRadioButtonBinding(BOOL *Value) + { +#ifdef UNICODE + return new PluginRadioButtonBinding(Info, &DialogHandle, DialogItemsCount-1, Value); +#else + return new RadioButtonBinding(Value); +#endif + } + + virtual DialogItemBinding* CreateComboBoxBinding(int *Value) + { +#ifdef UNICODE + return new PluginComboBoxBinding(Info, &DialogHandle, DialogItemsCount-1, Value); +#else + return new PluginComboBoxBinding(Value); +#endif + } + +public: + PluginDialogBuilder(const PluginStartupInfo &aInfo, int TitleMessageID, const TCHAR *aHelpTopic) + : DialogFlags(0), Info(aInfo), DialogHandle(NULL), HelpTopic(aHelpTopic) + { + AddBorder(GetLangString(TitleMessageID)); + } + + ~PluginDialogBuilder() + { +#ifdef UNICODE + if (DialogHandle) + { + Info.DialogFree(DialogHandle); + DialogHandle = NULL; + } +#endif + } + + FarDialogItem* GetItemByIndex(int Index) + { + if (Index >= 0 && Index < DialogItemsCount) + return (DialogItems + Index); + return NULL; + } + + int GetItemIndex(FarDialogItem* p) + { + return GetItemID(p); + } + + virtual FarDialogItem* AddIntEditField(int *Value, int Width) + { + FarDialogItem *Item = AddDialogItem(DI_FIXEDIT, EMPTY_TEXT); + Item->Flags |= DIF_MASKEDIT; + PluginIntEditFieldBinding *Binding; +#ifdef UNICODE + Binding = new PluginIntEditFieldBinding(Info, &DialogHandle, DialogItemsCount-1, Value, Width); + Item->PtrData = Binding->GetBuffer(); +#else + Binding = new PluginIntEditFieldBinding(Info, Value, Width); + Info.FSF->itoa(*Value, (TCHAR *) Item->Data, 10); +#endif + + +#ifdef _FAR_NO_NAMELESS_UNIONS + Item->Param.Mask = Binding->GetMask(); +#else + Item->Mask = Binding->GetMask(); +#endif + SetNextY(Item); + Item->X2 = Item->X1 + Width - 1; + SetLastItemBinding(Binding); + return Item; + } + + FarDialogItem* AddEditField(TCHAR *Value, int MaxSize, int Width, const TCHAR *HistoryID = nullptr) + { + FarDialogItem *Item = AddDialogItem(DI_EDIT, Value); + SetNextY(Item); + Item->X2 = Item->X1 + Width; + if (HistoryID) + { +#ifdef _FAR_NO_NAMELESS_UNIONS + Item->Param.History = HistoryID; +#else + Item->History = HistoryID; +#endif + Item->Flags |= DIF_HISTORY; + } + +#ifdef UNICODE + SetLastItemBinding(new PluginEditFieldBinding(Info, &DialogHandle, DialogItemsCount-1, Value, MaxSize)); +#else + SetLastItemBinding(new PluginEditFieldBinding(Value, MaxSize)); +#endif + return Item; + } +}; diff --git a/Uninstall/src/bak/EPlugin.cpp b/Uninstall/src/bak/EPlugin.cpp new file mode 100644 index 0000000..8840260 --- /dev/null +++ b/Uninstall/src/bak/EPlugin.cpp @@ -0,0 +1,91 @@ +static struct PluginStartupInfo Info; +static struct FarStandardFunctions FSF; + +const TCHAR* GetMsg(int MsgId) +{ + return(Info.GetMsg(Info.ModuleNumber,MsgId)); +} + +void ShowHelp(const TCHAR * HelpTopic) +{ + Info.ShowHelp(Info.ModuleName,HelpTopic,0); +} + +int EMessage(const TCHAR * const * s, int nType, int n) +{ + return Info.Message(Info.ModuleNumber, FMSG_ALLINONE|nType, NULL, s, + 0, //нв®в Ї а ¬Ґва ЇаЁ FMSG_ALLINONE ЁЈ­®аЁагҐвбп + n); //Є®«ЁзҐбвў® Є­®Ї®Є +} + +int DrawMessage(int nType, int n, char *msg, ...) +{ + int total = 0; + TCHAR * string = NULL; + + va_list ap; + TCHAR * arg; + + va_start(ap, msg); + while ((arg = va_arg(ap,TCHAR*))!= 0) + { + total += lstrlen(arg) + 1; //¬л ҐйҐ Ўг¤Ґ¬ § ЇЁблў вм бЁ¬ў®« ЇҐаҐў®¤  бва®ЄЁ + } + va_end(ap); + + total--; //Ї®б«Ґ¤­Ё© §­ Є ЇҐаҐў®¤  бва®ЄЁ ¬л б®в६ + + string = (TCHAR *) realloc(string, sizeof(TCHAR)*(total + 1)); + + string[0]=_T('\0'); + + va_start(ap, msg); + while ((arg = va_arg(ap,TCHAR*))!= NULL) + { + StringCchCat(string, total+1, arg); + StringCchCat(string, total+1, _T("\n")); + } + va_end(ap); + + string[total]=_T('\0'); + + int result = EMessage((const TCHAR * const *) string, nType, n); + realloc(string, 0); + return result; +} + +const TCHAR * strstri(const TCHAR *s, const TCHAR *c) +{ + if (c) + { + int l = lstrlen(c); + for (const TCHAR *p = s ; *p ; p++) + if (FSF.LStrnicmp(p, c, l) == 0) + return p; + } + return NULL; +} + +TCHAR * strnstri(TCHAR *s, const TCHAR *c, int n) +{ + if (c) + { + int l = min(lstrlen(c), n); + for (TCHAR *p = s ; *p ; p++) + if (FSF.LStrnicmp(p, c, l) == 0) + return p; + } + return NULL; +} + +TCHAR * unQuote(TCHAR *vStr) +{ + unsigned l; + l = lstrlen(vStr); + if (*vStr == _T('\"')) + memmove(vStr,vStr+1,l*sizeof(TCHAR)); + l = lstrlen(vStr); + if (vStr[l-1] == _T('\"')) + vStr[l-1] = _T('\0'); + return(vStr); +} diff --git a/Uninstall/src/bak/Registry.cpp b/Uninstall/src/bak/Registry.cpp new file mode 100644 index 0000000..5f3c286 --- /dev/null +++ b/Uninstall/src/bak/Registry.cpp @@ -0,0 +1,157 @@ +TCHAR PluginRootKey[80]; + +#define HKCU HKEY_CURRENT_USER +#define HKCR HKEY_CLASSES_ROOT +#define HKCC HKEY_CURRENT_CONFIG +#define HKLM HKEY_LOCAL_MACHINE +#define HKU HKEY_USERS + +/* + ”г­ЄжЁЁ а Ў®вл б ॥бв஬ + ’ॡгҐвбп ў­Ґи­пп ЇҐаҐ¬Ґ­­ п PluginRootKey +*/ + +#ifdef __cplusplus + +HKEY CreateRegKey(HKEY hRoot,TCHAR *Key); +HKEY OpenRegKey(HKEY hRoot,TCHAR *Key); + +// ¤«п §­ зҐ­Ёп б Ё¬Ґ­Ґ¬ ValueName гбв ­®ўЁвм §­ зҐ­ЁҐ вЁЇ  char* +void SetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,TCHAR *ValueData) +{ + HKEY hKey=CreateRegKey(hRoot,Key); + RegSetValueEx(hKey,ValueName,0,REG_SZ,(const BYTE*)ValueData,(lstrlen(ValueData)+1)*sizeof(TCHAR)); + RegCloseKey(hKey); +} + + +// гбв ­®ўЁвм §­ зҐ­ЁҐ вЁЇ  DWORD +void SetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,DWORD ValueData) +{ + HKEY hKey=CreateRegKey(hRoot,Key); + RegSetValueEx(hKey,ValueName,0,REG_DWORD,(BYTE *)&ValueData,sizeof(ValueData)); + RegCloseKey(hKey); +} + + +// гбв ­®ўЁвм §­ зҐ­ЁҐ вЁЇ  Binary +void SetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,BYTE *ValueData,DWORD ValueSize) +{ + HKEY hKey=CreateRegKey(hRoot,Key); + RegSetValueEx(hKey,ValueName,0,REG_BINARY,ValueData,ValueSize); + RegCloseKey(hKey); +} + + +// Ї®«гзЁвм ¤ ­­лҐ вЁЇ  char* +int GetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,TCHAR *ValueData,TCHAR *Default,DWORD DataSize) +{ + HKEY hKey=OpenRegKey(hRoot,Key); + DWORD Type; + DWORD Size = DataSize * sizeof(TCHAR); + int ExitCode=RegQueryValueEx(hKey,ValueName,0,&Type,(LPBYTE)ValueData,&Size); + ValueData[DataSize - 1] = 0; + RegCloseKey(hKey); + if (hKey==NULL || ExitCode!=ERROR_SUCCESS) + { + StringCchCopy(ValueData,DataSize,Default); + return(FALSE); + } + return(TRUE); +} + + +// Ї®«гзЁвм ¤ ­­лҐ вЁЇ  DWORD +int GetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,int &ValueData,DWORD Default) +{ + HKEY hKey=OpenRegKey(hRoot,Key); + DWORD Type,Size=sizeof(ValueData); + int ExitCode=RegQueryValueEx(hKey,ValueName,0,&Type,(BYTE *)&ValueData,&Size); + RegCloseKey(hKey); + if (hKey==NULL || ExitCode!=ERROR_SUCCESS) + { + ValueData=Default; + return(FALSE); + } + return(TRUE); +} + + +// Ї®«гзЁвм ¤ ­­лҐ вЁЇ  DWORD +int GetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,DWORD Default) +{ + int ValueData; + GetRegKey(hRoot,Key,ValueName,ValueData,Default); + return(ValueData); +} + + +// Ї®«гзЁвм ¤ ­­лҐ вЁЇ  Binary +int GetRegKey(HKEY hRoot,TCHAR *Key,TCHAR *ValueName,BYTE *ValueData,BYTE *Default,DWORD DataSize) +{ + HKEY hKey=OpenRegKey(hRoot,Key); + DWORD Type; + int ExitCode=RegQueryValueEx(hKey,ValueName,0,&Type,ValueData,&DataSize); + RegCloseKey(hKey); + if (hKey==NULL || ExitCode!=ERROR_SUCCESS) + { + if (Default!=NULL) + memcpy(ValueData,Default,DataSize); + else + memset(ValueData,0,DataSize); + return(FALSE); + } + return(TRUE); +} + + +// г¤ «пҐв Є«оз +void DeleteRegKey(HKEY hRoot,TCHAR *Key) +{ + TCHAR FullKeyName[512]; + StringCchCopy(FullKeyName,ARRAYSIZE(FullKeyName),PluginRootKey); + StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),(Key && *Key ? _T("\\"):_T(""))); + StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),Key); + RegDeleteKey(hRoot,FullKeyName); +} + + +// ᮧ¤ вм Є«оз +HKEY CreateRegKey(HKEY hRoot,TCHAR *Key) +{ + HKEY hKey; + DWORD Disposition; + TCHAR FullKeyName[512]; + StringCchCopy(FullKeyName,ARRAYSIZE(FullKeyName),PluginRootKey); + StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),(Key && *Key ? _T("\\"):_T(""))); + StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),Key); + if(RegCreateKeyEx(hRoot,FullKeyName,0,NULL,0,KEY_WRITE,NULL, + &hKey,&Disposition) != ERROR_SUCCESS) + hKey=NULL; + return(hKey); +} + + +// ®вЄалвм § ¤ ­­го ўҐвўм ॥бва  +HKEY OpenRegKey(HKEY hRoot,TCHAR *Key) +{ + HKEY hKey; + TCHAR FullKeyName[512]; + StringCchCopy(FullKeyName,ARRAYSIZE(FullKeyName),PluginRootKey); + StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),(Key && *Key ? _T("\\"):_T(""))); + StringCchCat(FullKeyName,ARRAYSIZE(FullKeyName),Key); + if (RegOpenKeyEx(hRoot,FullKeyName,0,KEY_QUERY_VALUE,&hKey)!=ERROR_SUCCESS) + return(NULL); + return(hKey); +} + +// Їа®ўҐаЁвм бгйҐбвў®ў ­ЁҐ Є«оз  +BOOL CheckRegKey(HKEY hRoot,TCHAR *Key) +{ + HKEY hKey=OpenRegKey(hRoot,Key); + if (hKey!=NULL) + RegCloseKey(hKey); + return(hKey!=NULL); +} + +#endif diff --git a/Uninstall/src/bak/UnInstall.cpp b/Uninstall/src/bak/UnInstall.cpp new file mode 100644 index 0000000..2332920 --- /dev/null +++ b/Uninstall/src/bak/UnInstall.cpp @@ -0,0 +1,542 @@ +#include +#include +#include +#include +#include +#include "plugin.hpp" +#include "memory.h" +#define realloc my_realloc +#ifndef nullptr + #define nullptr NULL +#endif +#ifndef _ASSERTE + #define _ASSERTE(x) +#endif +#include "DlgBuilder.hpp" +#include "eplugin.cpp" +#include "farcolor.hpp" +#include "farkeys.hpp" +#include "farlang.h" +#include "registry.cpp" +#include "uninstall.hpp" + +#ifdef FARAPI18 +# define SetStartupInfo SetStartupInfoW +# define GetPluginInfo GetPluginInfoW +# define OpenPlugin OpenPluginW +# define Configure ConfigureW +#endif + +#ifdef FARAPI17 +int WINAPI GetMinFarVersion(void) +{ + return MAKEFARVERSION(1,75,2555); +} +#endif +#ifdef FARAPI18 +int WINAPI GetMinFarVersion(void) +{ + return FARMANAGERVERSION; +} +int WINAPI GetMinFarVersionW(void) +{ + return FARMANAGERVERSION; +} +#endif + +void WINAPI SetStartupInfo(const struct PluginStartupInfo *psInfo) +{ + Info = *psInfo; + FSF = *psInfo->FSF; + Info.FSF = &FSF; + InitHeap(); + StringCchCopy(PluginRootKey,ARRAYSIZE(PluginRootKey),Info.RootKey); + StringCchCat(PluginRootKey,ARRAYSIZE(PluginRootKey),_T("\\UnInstall")); + ReadRegistry(); +} + +void WINAPI GetPluginInfo(struct PluginInfo *Info) +{ + static const TCHAR *PluginMenuStrings[1]; + PluginMenuStrings[0] = GetMsg(MPlugIn); + Info -> StructSize = sizeof(*Info); + Info -> PluginMenuStrings = PluginMenuStrings; + Info -> PluginConfigStrings = PluginMenuStrings; + if (Opt.WhereWork & 2) + Info -> Flags |= PF_EDITOR; + if (Opt.WhereWork & 1) + Info -> Flags |= PF_VIEWER; + Info -> PluginMenuStringsNumber = ARRAYSIZE(PluginMenuStrings); + Info -> PluginConfigStringsNumber = ARRAYSIZE(PluginMenuStrings); +} + +void ResizeDialog(HANDLE hDlg) { + CONSOLE_SCREEN_BUFFER_INFO con_info; + GetConsoleScreenBufferInfo(hStdout, &con_info); + unsigned con_sx = con_info.srWindow.Right - con_info.srWindow.Left + 1; + int max_items = con_info.srWindow.Bottom - con_info.srWindow.Top + 1 - 7; + int s = ((ListSize>0) && (ListSize0 ? max_items : 0)); + SMALL_RECT NewPos = { 2, 1, con_sx - 7, s + 2 }; + SMALL_RECT OldPos; + Info.SendDlgMessage(hDlg,DM_GETITEMPOSITION,LIST_BOX,reinterpret_cast(&OldPos)); + if (NewPos.Right!=OldPos.Right || NewPos.Bottom!=OldPos.Bottom) { + COORD coord; + coord.X = con_sx - 4; + coord.Y = s + 4; + Info.SendDlgMessage(hDlg,DM_RESIZEDIALOG,0,reinterpret_cast(&coord)); + coord.X = -1; + coord.Y = -1; + Info.SendDlgMessage(hDlg,DM_MOVEDIALOG,TRUE,reinterpret_cast(&coord)); + Info.SendDlgMessage(hDlg,DM_SETITEMPOSITION,LIST_BOX,reinterpret_cast(&NewPos)); + } +} + +static LONG_PTR WINAPI DlgProc(HANDLE hDlg,int Msg,int Param1,LONG_PTR Param2) +{ + static TCHAR Filter[MAX_PATH]; + static TCHAR spFilter[MAX_PATH]; + static FarListTitles ListTitle; + + switch(Msg) + { + case DN_RESIZECONSOLE: + { + Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,FALSE,0); + ResizeDialog(hDlg); + Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,TRUE,0); + } + return TRUE; + + case DMU_UPDATE: + { + int OldPos = static_cast(Info.SendDlgMessage(hDlg,DM_LISTGETCURPOS,LIST_BOX,0)); + + if (Param1) + UpDateInfo(); + + ListSize = 0; + int NewPos = -1; + if (OldPos >= 0 && OldPos < nCount) + { + if (!*Filter || strstri(p[OldPos].Keys[DisplayName],Filter)) //без учета регистра в OEM кодировке + NewPos = OldPos; + } + for (int i = 0; i < nCount; i++) + { + const TCHAR* DispName = p[i].Keys[DisplayName], *Find; + if (*Filter) + Find = strstri(DispName,Filter); + else + Find = DispName; + if (Find != nullptr) //без учета регистра в OEM кодировке + { + FLI[i].Flags &= ~LIF_HIDDEN; + if (Param2 && (i == OldPos)) + { + if (FLI[i].Flags & LIF_CHECKED) + { + FLI[i].Flags &= ~LIF_CHECKED; + } + else + { + FLI[i].Flags |= LIF_CHECKED; + } + } + //без учета регистра - а кодировка ANSI + if (NewPos == -1 && Find == DispName) + NewPos = i; + ListSize++; + } + else + FLI[i].Flags |= LIF_HIDDEN; + } + if (Param1 == 0 && Param2) + { + // Снятие или установка пометки (Ins) + if (Param2 == 1) + { + for (int i = (OldPos+1); i < nCount; i++) + { + if (!(FLI[i].Flags & LIF_HIDDEN)) + { + OldPos = i; break; + } + } + NewPos = OldPos; + } + // Снятие или установка пометки (RClick) + else if (Param2 == 2) + { + NewPos = OldPos; + } + } + else if (NewPos == -1) + { + NewPos = OldPos; + } + + Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,FALSE,0); + + Info.SendDlgMessage(hDlg,DM_LISTSET,LIST_BOX,reinterpret_cast(&FL)); + + StringCchPrintf(spFilter,ARRAYSIZE(spFilter), GetMsg(MFilter),Filter,ListSize,nCount); + ListTitle.Title = spFilter; + ListTitle.TitleLen = lstrlen(spFilter); + Info.SendDlgMessage(hDlg,DM_LISTSETTITLES,LIST_BOX,reinterpret_cast(&ListTitle)); + + ResizeDialog(hDlg); + + struct FarListPos FLP; + FLP.SelectPos = NewPos; + FLP.TopPos = -1; + Info.SendDlgMessage(hDlg,DM_LISTSETCURPOS,LIST_BOX,reinterpret_cast(&FLP)); + + Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,TRUE,0); + } + break; + + case DN_INITDIALOG: + { + StringCchCopy(Filter,ARRAYSIZE(Filter),_T("")); + ListTitle.Bottom = const_cast(GetMsg(MBottomLine)); + ListTitle.BottomLen = lstrlen(GetMsg(MBottomLine)); + + //подстраиваемся под размеры консоли + Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,FALSE,0); + ResizeDialog(hDlg); + Info.SendDlgMessage(hDlg,DM_ENABLEREDRAW,TRUE,0); + //заполняем диалог + Info.SendDlgMessage(hDlg,DMU_UPDATE,1,0); + } + break; + + case DN_MOUSECLICK: + { + if (Param1 == LIST_BOX) + { + MOUSE_EVENT_RECORD *mer = (MOUSE_EVENT_RECORD *)Param2; + if (mer->dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED) + { + // find list on-screen coords (excluding frame and border) + SMALL_RECT list_rect; + Info.SendDlgMessage(hDlg, DM_GETDLGRECT, 0, reinterpret_cast(&list_rect)); + list_rect.Left += 2; + list_rect.Top += 1; + list_rect.Right -= 2; + list_rect.Bottom -= 1; + if ((mer->dwEventFlags == 0) && (mer->dwMousePosition.X > list_rect.Left) && (mer->dwMousePosition.X < list_rect.Right) && (mer->dwMousePosition.Y > list_rect.Top) && (mer->dwMousePosition.Y < list_rect.Bottom)) + { + DlgProc(hDlg, DN_KEY, LIST_BOX, KEY_ENTER); + return TRUE; + } + // pass message to scrollbar if needed + if ((mer->dwMousePosition.X == list_rect.Right) && (mer->dwMousePosition.Y > list_rect.Top) && (mer->dwMousePosition.Y < list_rect.Bottom)) return FALSE; + return TRUE; + } + else if (mer->dwButtonState == RIGHTMOST_BUTTON_PRESSED) + { + Info.SendDlgMessage(hDlg,DMU_UPDATE,0,2); + return TRUE; + } + } + } + break; + + case DN_KEY: + switch (Param2) + { + case KEY_F8: + { + if (ListSize) + { + TCHAR DlgText[MAX_PATH + 200]; + StringCchPrintf(DlgText, ARRAYSIZE(DlgText), GetMsg(MConfirm), p[Info.SendDlgMessage(hDlg,DM_LISTGETCURPOS,LIST_BOX,NULL)].Keys[DisplayName]); + if (EMessage((const TCHAR * const *) DlgText, 0, 2) == 0) + { + if (!DeleteEntry(static_cast(Info.SendDlgMessage(hDlg,DM_LISTGETCURPOS,LIST_BOX,NULL)))) + DrawMessage(FMSG_WARNING, 1, "%s",GetMsg(MPlugIn),GetMsg(MDelRegErr),GetMsg(MBtnOk),NULL); + Info.SendDlgMessage(hDlg,DMU_UPDATE,1,0); + } + } + } + return TRUE; + + case (KEY_F9|KEY_SHIFT|KEY_ALT): + case (KEY_F9): + { + Configure(0); + } + return TRUE; + + case KEY_CTRLR: + { + Info.SendDlgMessage(hDlg,DMU_UPDATE,1,0); + } + return TRUE; + + case KEY_INS: + { + Info.SendDlgMessage(hDlg,DMU_UPDATE,0,1); + } + return TRUE; + + case KEY_ENTER: + case KEY_SHIFTENTER: + { + if (ListSize) + { + int liChanged = 0; + int liSelected = 0, liFirst = -1; + + for (int i = 0; i < nCount; i++) + { + if (FLI[i].Flags & LIF_CHECKED) + { + if (liFirst == -1) + liFirst = i; + liSelected++; + } + } + + if (liSelected <= 1) + { + int liAction = (Param2 == KEY_ENTER) ? Opt.EnterAction : Opt.ShiftEnterAction; + int pos = (liFirst == -1) ? static_cast(Info.SendDlgMessage(hDlg,DM_LISTGETCURPOS,LIST_BOX,NULL)) : liFirst; + liChanged = ExecuteEntry(pos, liAction, (Opt.RunLowPriority!=0)); + } + else + { + int liAction = (Param2 == KEY_ENTER) ? Opt.EnterAction : Opt.ShiftEnterAction; + bool LowPriority = (Opt.RunLowPriority!=0); + + // Обязательно ожидание - два инсталлятора сразу недопускаются + if (liAction == Action_Menu) + { + if (EntryMenu(0, liAction, LowPriority, liSelected) < 0) + return TRUE; + } + else if (liAction == Action_Uninstall) + liAction = Action_UninstallWait; + else if (liAction == Action_Modify) + liAction = Action_ModifyWait; + else if (liAction == Action_Repair) + liAction = Action_RepairWait; + + for (int pos = 0; pos < nCount; pos++) + { + if (!(FLI[pos].Flags & LIF_CHECKED)) + continue; + struct FarListPos FLP; + FLP.SelectPos = pos; + FLP.TopPos = -1; + Info.SendDlgMessage(hDlg,DM_LISTSETCURPOS,LIST_BOX,reinterpret_cast(&FLP)); + int li = ExecuteEntry(pos, liAction, LowPriority); + if (li == -1) + break; // отмена + if (li == 1) + liChanged = 1; + } + } + + if (liChanged == 1) + { + Info.SendDlgMessage(hDlg,DMU_UPDATE,1,0); + } + } + } + return TRUE; + + case KEY_SHIFTINS: + case KEY_CTRLV: + { + TCHAR * bufP = FSF.PasteFromClipboard(); + static TCHAR bufData[MAX_PATH]; + if (bufP) + { + StringCchCopy(bufData,ARRAYSIZE(bufData),bufP); + FSF.DeleteBuffer(bufP); + unQuote(bufData); + FSF.LStrlwr(bufData); + for (int i = lstrlen(bufData); i >= 1; i--) + for (int j = 0; j < nCount; j++) + if (strnstri(p[j].Keys[DisplayName],bufData,i)) + { + lstrcpyn(Filter,bufData,i+1); + Info.SendDlgMessage(hDlg,DMU_UPDATE,0,0); + return TRUE; + } + } + } + return TRUE; + + case KEY_DEL: + { + if (lstrlen(Filter) > 0) + { + StringCchCopy(Filter,ARRAYSIZE(Filter),_T("")); + Info.SendDlgMessage(hDlg,DMU_UPDATE,0,0); + } + } + return TRUE; + + case KEY_F3: + case KEY_F4: + { + if (ListSize) + { + DisplayEntry(static_cast(Info.SendDlgMessage(hDlg,DM_LISTGETCURPOS,LIST_BOX,NULL))); + Info.SendDlgMessage(hDlg,DM_REDRAW,NULL,NULL); + } + } + return TRUE; + + case KEY_F2: + { + Opt.SortByDate = !Opt.SortByDate; + Info.SendDlgMessage(hDlg,DMU_UPDATE,1,0); + } + return TRUE; + + case KEY_BS: + { + if (lstrlen(Filter)) + { + Filter[lstrlen(Filter)-1] = '\0'; + Info.SendDlgMessage(hDlg,DMU_UPDATE,0,0); + } + } + return TRUE; + + default: + { + if (Param2 >= KEY_SPACE && Param2 < KEY_FKEY_BEGIN) + { + struct FarListInfo ListInfo; + Info.SendDlgMessage(hDlg,DM_LISTINFO,LIST_BOX,reinterpret_cast(&ListInfo)); + if ((lstrlen(Filter) < sizeof(Filter)) && ListInfo.ItemsNumber) + { + int filterL = lstrlen(Filter); + Filter[filterL] = FSF.LLower(static_cast(Param2)); + Filter[filterL+1] = '\0'; + Info.SendDlgMessage(hDlg,DMU_UPDATE,0,0); + return TRUE; + } + } + } + } + return FALSE; + + case DN_CTLCOLORDIALOG: + return Info.AdvControl(Info.ModuleNumber,ACTL_GETCOLOR,(void *)COL_MENUTEXT); + + case DN_CTLCOLORDLGLIST: + if (Param1 == LIST_BOX) + { + FarListColors *Colors = (FarListColors *)Param2; + int ColorIndex[] = { COL_MENUBOX, COL_MENUBOX, COL_MENUTITLE, COL_MENUTEXT, COL_MENUHIGHLIGHT, COL_MENUBOX, COL_MENUSELECTEDTEXT, COL_MENUSELECTEDHIGHLIGHT, COL_MENUSCROLLBAR, COL_MENUDISABLEDTEXT, COL_MENUARROWS, COL_MENUARROWSSELECTED, COL_MENUARROWSDISABLED }; + int Count = ARRAYSIZE(ColorIndex); + if (Count > Colors->ColorCount) + Count = Colors->ColorCount; + for (int i = 0; i < Count; i++) + Colors->Colors[i] = static_cast(Info.AdvControl(Info.ModuleNumber, ACTL_GETCOLOR, reinterpret_cast(ColorIndex[i]))); + return TRUE; + } + break; + } + return Info.DefDlgProc(hDlg,Msg,Param1,Param2); +} + +HANDLE WINAPI OpenPlugin(int /*OpenFrom*/, INT_PTR /*Item*/) +{ + ReadRegistry(); + struct FarDialogItem DialogItems[1]; + ZeroMemory(DialogItems, sizeof(DialogItems)); + p = NULL; + FLI = NULL; + + hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + UpDateInfo(); + + DialogItems[0].Type = DI_LISTBOX; + DialogItems[0].Flags = DIF_LISTNOAMPERSAND; + DialogItems[0].X1 = 2; + DialogItems[0].Y1 = 1; + +#ifdef FARAPI17 + Info.DialogEx(Info.ModuleNumber,-1,-1,0,0,"Contents",DialogItems,ARRAYSIZE(DialogItems),0,0,DlgProc,0); +#endif +#ifdef FARAPI18 + HANDLE h_dlg = Info.DialogInit(Info.ModuleNumber,-1,-1,0,0,L"Contents",DialogItems,ARRAYSIZE(DialogItems),0,0,DlgProc,0); + if (h_dlg != INVALID_HANDLE_VALUE) { + Info.DialogRun(h_dlg); + Info.DialogFree(h_dlg); + } +#endif + FLI = (FarListItem *) realloc(FLI, 0); + p = (KeyInfo *) realloc(p, 0); + return INVALID_HANDLE_VALUE; +} + +int WINAPI Configure(int ItemNumber) +{ + PluginDialogBuilder Config(Info, MPlugIn, _T("Configuration")); + FarDialogItem *p1, *p2; + + BOOL bShowInViewer = (Opt.WhereWork & 1) != 0; + BOOL bShowInEditor = (Opt.WhereWork & 2) != 0; + //BOOL bEnterWaitCompletion = (Opt.EnterFunction != 0); + BOOL bUseElevation = (Opt.UseElevation != 0); + BOOL bLowPriority = (Opt.RunLowPriority != 0); + BOOL bForceMsiUse = (Opt.ForceMsiUse != 0); + + Config.AddCheckbox(MShowInEditor, &bShowInEditor); + Config.AddCheckbox(MShowInViewer, &bShowInViewer); + //Config.AddCheckbox(MEnterWaitCompletion, &bEnterWaitCompletion); + Config.AddCheckbox(MUseElevation, &bUseElevation); + Config.AddCheckbox(MLowPriority, &bUseElevation); + Config.AddCheckbox(MForceMsiUse, &bForceMsiUse); + + Config.AddSeparator(); + + FarList AEnter, AShiftEnter; + AEnter.ItemsNumber = AShiftEnter.ItemsNumber = 7; + AEnter.Items = (FarListItem*)calloc(AEnter.ItemsNumber,sizeof(FarListItem)); + AShiftEnter.Items = (FarListItem*)calloc(AEnter.ItemsNumber,sizeof(FarListItem)); + for (int i = 0; i < AEnter.ItemsNumber; i++) + { + #ifdef FARAPI18 + AEnter.Items[i].Text = GetMsg(MActionUninstallWait+i); + AShiftEnter.Items[i].Text = AEnter.Items[i].Text; + #else + StringCchCopy(AEnter.Items[i].Text,ARRAYSIZE(AEnter.Items[i].Text),GetMsg(MActionUninstallWait+i)); + StringCchCopy(AShiftEnter.Items[i].Text,ARRAYSIZE(AShiftEnter.Items[i].Text),AEnter.Items[i].Text); + #endif + } + + p1 = Config.AddText(MEnterAction); p2 = Config.AddComboBox(23, &AEnter, &Opt.EnterAction); + Config.MoveItemAfter(p1,p2); + p1 = Config.AddText(MShiftEnterAction); p2 = Config.AddComboBox(23, &AShiftEnter, &Opt.ShiftEnterAction); + Config.MoveItemAfter(p1,p2); + + + + Config.AddOKCancel(MBtnOk, MBtnCancel); + + if (Config.ShowDialog()) + { + Opt.WhereWork = (bShowInViewer ? 1 : 0) | (bShowInEditor ? 2 : 0); + //Opt.EnterFunction = bEnterWaitCompletion; + Opt.UseElevation = bUseElevation; + Opt.RunLowPriority = bLowPriority; + Opt.ForceMsiUse = bForceMsiUse; + + SetRegKey(HKCU,_T(""),_T("WhereWork"),(DWORD) Opt.WhereWork); + SetRegKey(HKCU,_T(""),_T("EnterAction"),(DWORD) Opt.EnterAction); + SetRegKey(HKCU,_T(""),_T("ShiftEnterAction"),(DWORD) Opt.ShiftEnterAction); + SetRegKey(HKCU,_T(""),_T("UseElevation"),(DWORD) Opt.UseElevation); + SetRegKey(HKCU,_T(""),_T("RunLowPriority"),(DWORD) Opt.RunLowPriority); + SetRegKey(HKCU,_T(""),_T("ForceMsiUse"),(DWORD) Opt.ForceMsiUse); + } + + return FALSE; +} diff --git a/Uninstall/src/bak/UnInstall.hpp b/Uninstall/src/bak/UnInstall.hpp new file mode 100644 index 0000000..bd3d6d6 --- /dev/null +++ b/Uninstall/src/bak/UnInstall.hpp @@ -0,0 +1,1070 @@ +//дополнительные описания к ключам +const TCHAR *HelpTopics[] = +{ + _T("DisplayName"), + _T(""), + _T("InstallLocation"), + _T("ModifyPath"), + _T("UninstallString"), + _T("Publisher"), + _T("URLInfoAbout"), + _T("URLUpdateInfo"), + _T("Comments"), + _T("DisplayVersion"), + _T("InstallDate") // Must be last item! +}; + +const TCHAR *HiddenPrefixes[] = +{ + _T("InstallWIX_{"), + _T("InstallShield_{") +}; + +enum +{ + LIST_BOX, + DMU_UPDATE = DM_USER+1 +}; + +enum ActionEnum +{ + Action_UninstallWait = 0, + Action_Uninstall, + Action_ModifyWait, + Action_Modify, + Action_RepairWait, + Action_Repair, + Action_Menu, +}; + +//enum ActionMenuEnum +//{ +// ActionMenu_UninstallWait = 0, +// ActionMenu_Uninstall, +// ActionMenu_ModifyWait, +// ActionMenu_Modify, +// ActionMenu_RepairWait, +// ActionMenu_Repair, +//}; + +enum +{ + DisplayName, + RegLocation, + InstallLocation, + ModifyPath, + UninstallString, + Publisher, + URLInfoAbout, + URLUpdateInfo, + Comments, + DisplayVersion, + InstallDate +}; + +const int KeysCount = ARRAYSIZE(HelpTopics); +struct RegKeyPath { + HKEY Root; + const TCHAR* Path; +} UninstKeys[] = { + { HKEY_CURRENT_USER, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall") }, + { HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall") }, +}; +int nCount; // сколько всего элементов +int nRealCount; // сколько выделено памяти +FarList FL; +FarListItem* FLI = NULL; +int ListSize; +HANDLE hStdout; + +struct Options +{ + int WhereWork; //<- TechInfo + //int EnterFunction; //<- TechInfo + int EnterAction; // enum ActionEnum + int ShiftEnterAction; // enum ActionEnum + int UseElevation; //<- TechInfo + int RunLowPriority; + int ForceMsiUse; + bool SortByDate; +} Opt; + +struct KeyInfo +{ + TCHAR Keys[KeysCount][MAX_PATH]; +#ifdef FARAPI18 + TCHAR ListItem[MAX_PATH]; +#endif + bool Avail[KeysCount]; + RegKeyPath RegKey; + FILETIME RegTime; + TCHAR InstDate[10]; + DWORD InstDateN; + REGSAM RegView; + TCHAR SubKeyName[MAX_PATH]; + bool WindowsInstaller; + bool Hidden; + bool NoModify, NoRepair; + bool CanModify, CanRepair; +} *p = NULL; + +bool ValidGuid(const TCHAR* guid) +{ + const unsigned c_max_guid_len = 38; + wchar_t buf[c_max_guid_len + 1]; + ZeroMemory(buf, sizeof(buf)); + unsigned l = lstrlen(guid); + for (unsigned i = 0; (i < c_max_guid_len) && (i < l); i++) buf[i] = guid[i]; + IID iid; + return IIDFromString(buf, &iid) == S_OK; +} + +//чтение реестра +bool FillReg(KeyInfo& key, TCHAR* Buf, RegKeyPath& RegKey, REGSAM RegView) +{ + HKEY userKey; + DWORD regType; + TCHAR fullN[MAX_PATH*2], *pszNamePtr; + LONG ExitCode; + DWORD bufSize, dwTest; + + memset(&key, 0, sizeof(key)); + + key.RegKey = RegKey; + key.RegView = RegView; + StringCchCopy(key.SubKeyName,ARRAYSIZE(key.SubKeyName),Buf); + StringCchCopy(fullN,ARRAYSIZE(fullN),key.RegKey.Path); + StringCchCat(fullN,ARRAYSIZE(fullN),_T("\\")); + pszNamePtr = fullN + _tcslen(fullN); + StringCchCat(fullN,ARRAYSIZE(fullN),key.SubKeyName); + if (RegOpenKeyEx(key.RegKey.Root, fullN, 0, KEY_READ | RegView, &userKey) != ERROR_SUCCESS) + return FALSE; + // "InstallWIX_{GUID}", "InstallShield_{" + for (int h = 0; h < ARRAYSIZE(HiddenPrefixes); h++) + { + int nPrefixLen = lstrlen(HiddenPrefixes[h]); + if (memcmp(key.SubKeyName, HiddenPrefixes[h], nPrefixLen*sizeof(TCHAR)) == 0 + && ValidGuid(key.SubKeyName+nPrefixLen-1)) + { + // Это может быть "ссылка" на гуид продукта + *pszNamePtr = 0; + StringCchCat(fullN,ARRAYSIZE(fullN),key.SubKeyName+nPrefixLen-1); + HKEY hTestKey; + if (RegOpenKeyEx(key.RegKey.Root, fullN, 0, KEY_READ | RegView, &hTestKey) == ERROR_SUCCESS) + { + key.Hidden = true; + RegCloseKey(hTestKey); + } + } + } + key.WindowsInstaller = (RegQueryValueEx(userKey,_T("WindowsInstaller"),0,NULL,NULL,NULL) == ERROR_SUCCESS) && ValidGuid(key.SubKeyName); + key.NoModify = (RegQueryValueEx(userKey,_T("NoModify"),0,NULL,(LPBYTE)&dwTest,&(bufSize)) == ERROR_SUCCESS) && (dwTest!=0); + key.NoRepair = (RegQueryValueEx(userKey,_T("NoRepair"),0,NULL,(LPBYTE)&dwTest,&(bufSize)) == ERROR_SUCCESS) && (dwTest!=0); + TCHAR sKeyTime[64]; int nKeyTimeLen; + if (RegQueryInfoKey(userKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&key.RegTime) != ERROR_SUCCESS) + { + memset(&key.RegTime, 0, sizeof(key.RegTime)); + //key.Keys[InstallDate][0] = 0; + sKeyTime[0] = 0; nKeyTimeLen = 0; + } + else + { + SYSTEMTIME st; FILETIME ft; + FileTimeToLocalFileTime(&key.RegTime, &ft); + FileTimeToSystemTime(&ft, &st); + StringCchPrintf(sKeyTime, ARRAYSIZE(sKeyTime), _T(" / %02u.%02u.%04u %u:%02u:%02u"), st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute, st.wSecond); + StringCchPrintf(key.InstDate, ARRAYSIZE(key.InstDate), _T("%02u.%02u.%02u"), st.wDay, st.wMonth, (st.wYear % 100)); + key.InstDateN = ((st.wYear & 0xFFFF) << 16) | ((st.wMonth & 0xFF) << 8) | (st.wDay & 0xFF); + nKeyTimeLen = lstrlen(sKeyTime) + 1; + } + for (int i=0;i(&item)); id++) + { + if (item.Type == DI_EDIT) + Info.SendDlgMessage(hDlg, DM_EDITUNCHANGEDFLAG, id, 0); + } + } + break; + case DN_KEY: + { + if ((Param2 == KEY_PGUP) || (Param2 == KEY_PGDN)) + { + TCHAR sMacro[32]; + if (Param2 == KEY_PGUP) + StringCchCopy(sMacro, ARRAYSIZE(sMacro), _T("Esc Up F3")); + else + StringCchCopy(sMacro, ARRAYSIZE(sMacro), _T("Esc Down F3")); + + ActlKeyMacro m = {MCMD_POSTMACROSTRING}; + m.Param.PlainText.SequenceText = sMacro; + m.Param.PlainText.Flags = KSFLAGS_DISABLEOUTPUT; + Info.AdvControl(Info.ModuleNumber, ACTL_KEYMACRO, &m); + + return TRUE; + } + } + break; + } + return Info.DefDlgProc(hDlg,Msg,Param1,Param2); +} + +//заполнение пункта диалога +void FillDialog(FarDialogItem & DialogItem, int Type, int X1, int Y1, int X2, int Y2, + int Flags, int nData) +{ + const TCHAR* s = nData != -1 ? GetMsg(nData) : _T(""); +#ifdef FARAPI17 + lstrcpy(DialogItem.Data, s); +#endif +#ifdef FARAPI18 + DialogItem.PtrData = s; +#endif + + DialogItem.X1 = X1; + DialogItem.X2 = X2; + DialogItem.Y1 = Y1; + DialogItem.Y2 = Y2; + + DialogItem.Flags = Flags; + DialogItem.Type = Type; + DialogItem.Selected = 0; + DialogItem.DefaultButton = 0; + DialogItem.Focus = 0; + + if (Type == DI_BUTTON) + { + DialogItem.DefaultButton = 1; + DialogItem.Focus = 1; + } +} + +void DisplayEntry(int Sel) +{ + unsigned sx = 70; + + unsigned max_len = 0; + unsigned cnt = 0; + for (int i=0;i sx) sx = len + 3; + cnt++; + } + } + + unsigned con_sx = 80; + HANDLE con = GetStdHandle(STD_OUTPUT_HANDLE); + if (con != INVALID_HANDLE_VALUE) { + CONSOLE_SCREEN_BUFFER_INFO con_info; + if (GetConsoleScreenBufferInfo(con, &con_info)) { + con_sx = con_info.srWindow.Right - con_info.srWindow.Left + 1; + } + } + + if (sx + 10 > con_sx) sx = con_sx - 10; + unsigned sy = cnt * 2; + + unsigned di_cnt = cnt * 2 + 2; + FarDialogItem* DialogItems = new FarDialogItem[di_cnt]; + unsigned y = 2; + unsigned idx = 1; + for (int i=0;i') || + wcschr(asFilePath, L'<') || + wcschr(asFilePath, L'|') + ) + return FALSE; + + // Пропуск UNC "\\?\" + if (asFilePath[0] == L'\\' && asFilePath[1] == L'\\' && asFilePath[2] == L'?' && asFilePath[3] == L'\\') + asFilePath += 4; + + // Если asFilePath содержит два (и более) ":\" + LPCWSTR pszColon = wcschr(asFilePath, L':'); + if (pszColon) + { + // Если есть ":", то это должен быть путь вида "X:\xxx", т.е. ":" - второй символ + if (pszColon != (asFilePath+1)) + return FALSE; + if (wcschr(pszColon+1, L':')) + return FALSE; + } + + // May be file path + return TRUE; +} + +BOOL FirstArg(LPCTSTR asCmdLine, TCHAR* rsArg/*[MAX_PATH+1]*/, LPCTSTR* rsNextArg) +{ + LPCTSTR psCmdLine = asCmdLine; + LPCTSTR pch = NULL; + TCHAR ch = *psCmdLine; + size_t nArgLen = 0; + + while (ch == _T(' ') || ch == _T('\t') || ch == _T('\r') || ch == _T('\n')) ch = *(++psCmdLine); + if (ch == 0) return FALSE; + + // аргумент начинается с " + if (ch == _T('"')) + { + psCmdLine++; + pch = wcschr(psCmdLine, _T('"')); + if (!pch) return FALSE; + while (pch[1] == _T('"')) + { + pch += 2; + pch = wcschr(pch, _T('"')); + if (!pch) return FALSE; + } + // Теперь в pch ссылка на последнюю " + } + else + { + // До конца строки или до первого пробела + //pch = wcschr(psCmdLine, _T(' ')); + // 09.06.2009 Maks - обломался на: cmd /c" echo Y " + pch = psCmdLine; + // Ищем обычным образом (до пробела/кавычки) + while (*pch && *pch!=_T(' ') && *pch!=_T('"')) pch++; + //if (!pch) pch = psCmdLine + lstrlenW(psCmdLine); // до конца строки + } + + nArgLen = pch - psCmdLine; + if (nArgLen > MAX_PATH) return FALSE; + + // Вернуть аргумент + memcpy(rsArg, psCmdLine, nArgLen*sizeof(TCHAR)); + rsArg[nArgLen] = 0; + + psCmdLine = pch; + + // Finalize + ch = *psCmdLine; // может указывать на закрывающую кавычку + if (ch == L'"') ch = *(++psCmdLine); + while (ch == L' ' || ch == L'\t' || ch == L'\r' || ch == L'\n') ch = *(++psCmdLine); + *rsNextArg = psCmdLine; + + return TRUE; +} + +int EntryMenu(int Sel, int& Action, bool& LowPriority, int nChkCount = 0) +{ +#ifdef FARAPI18 +#define SETITEM(i,s) items[i].Text = GetMsg(s) +#else +#define SETITEM(i,s) items[i].Text.TextPtr = GetMsg(s); items[i].Flags |= MIF_USETEXTPTR +#endif + FarMenuItemEx items[6]; memset(items, 0, sizeof(items)); + SETITEM(Action_UninstallWait, MActionUninstallWait); + SETITEM(Action_Uninstall, MActionUninstall); + if (nChkCount > 1) + items[Action_Uninstall].Flags |= MIF_DISABLE; + SETITEM(Action_ModifyWait, MActionModifyWait); + SETITEM(Action_Modify, MActionModify); + if (nChkCount > 1) + items[Action_Modify].Flags |= MIF_DISABLE; + else if (!p[Sel].CanModify) + { + items[Action_Modify].Flags |= MIF_DISABLE; + items[Action_ModifyWait].Flags |= MIF_DISABLE; + } + SETITEM(Action_RepairWait, MActionRepairWait); + SETITEM(Action_Repair, MActionRepair); + if (nChkCount > 1) + items[Action_Repair].Flags |= MIF_DISABLE; + else if (!p[Sel].CanRepair) + { + items[Action_Repair].Flags |= MIF_DISABLE; + items[Action_RepairWait].Flags |= MIF_DISABLE; + } + + int iRc; + int BreakCode; + int BreakKeys[2]={VK_F7,0}; + TCHAR szMenuTitle[MAX_PATH]; + + if (nChkCount > 1) + StringCchPrintf(szMenuTitle, ARRAYSIZE(szMenuTitle), GetMsg(MMenuTopLineN), nChkCount); + else + StringCchCopy(szMenuTitle, ARRAYSIZE(szMenuTitle), GetMsg(MMenuTopLine)); + + while (true) + { + iRc = Info.Menu(Info.ModuleNumber, -1,-1,0, FMENU_USEEXT|FMENU_WRAPMODE, szMenuTitle, + GetMsg(LowPriority ? MMenuBottomLine2 : MMenuBottomLine1), + _T("ActionMenu"), BreakKeys, &BreakCode, (struct FarMenuItem *)items, ARRAYSIZE(items)); + if (iRc < 0) + return -1; + if (BreakCode == 0) + { + LowPriority = !LowPriority; + for (UINT i = 0; i < ARRAYSIZE(items); i++) + { + if (i == iRc) + items[i].Flags |= MIF_SELECTED; + else + items[i].Flags &= ~MIF_SELECTED; + } + } + else + { + Action = iRc; + break; + } + } + + if ((Action & 0xFF) == Action_Menu) + return -1; // ошибка + + return Action; +} + +int ExecuteEntry(int Sel, int Action, bool LowPriority) +{ + if ((Action & 0xFF) == Action_Menu) + { + if (EntryMenu(Sel, Action, LowPriority) < 0) + return -1; + if ((Action & 0xFF) == Action_Menu) + return -1; // ошибка + } + + int nWaitSucceeded = 0; + STARTUPINFO si; + PROCESS_INFORMATION pi; + HANDLE hScreen; //for SaveScreen/RestoreScreen + + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); + + TCHAR cmd_line[MAX_PATH*2+1], cmd_file[MAX_PATH+1], cmd_parm[MAX_PATH*2+1]; + + LPCTSTR pszString = NULL; + + if ((Action == Action_ModifyWait) || (Action == Action_Modify)) + pszString = p[Sel].Keys[ModifyPath]; + //else if ((Action == Action_RepairWait) || (Action == Action_Repair)) + // pszString = NULL; + else if ((Action == Action_UninstallWait) || (Action == Action_Uninstall)) + { + if (!p[Sel].WindowsInstaller) + pszString = p[Sel].Keys[UninstallString]; + } + + if (pszString && !*pszString) + pszString = NULL; + + + if (p[Sel].WindowsInstaller && !(!Opt.ForceMsiUse && pszString)) + { + TCHAR szCode[6]; + if ((Action == Action_UninstallWait) || (Action == Action_Uninstall)) + StringCchCopy(szCode, ARRAYSIZE(szCode), _T(" /x ")); + else if ((Action == Action_RepairWait) || (Action == Action_Repair)) + StringCchCopy(szCode, ARRAYSIZE(szCode), _T(" /fa ")); + else //if ((Action == Action_ModifyWait) || (Action == Action_Modify)) + StringCchCopy(szCode, ARRAYSIZE(szCode), _T(" /i ")); + // Для CreateProcess + StringCchCopy(cmd_line, ARRAYSIZE(cmd_line), _T("msiexec")); + StringCchCat(cmd_line, ARRAYSIZE(cmd_line), szCode); + StringCchCat(cmd_line, ARRAYSIZE(cmd_line), p[Sel].SubKeyName); + // Для ShellExecuteEx + if (LowPriority) + { + StringCchCopy(cmd_file, ARRAYSIZE(cmd_parm), _T("cmd")); + StringCchCopy(cmd_parm, ARRAYSIZE(cmd_parm), _T("/c start /low ")); + StringCchCat(cmd_parm, ARRAYSIZE(cmd_parm), _T("msiexec")); + StringCchCat(cmd_parm, ARRAYSIZE(cmd_parm), szCode); + StringCchCat(cmd_parm, ARRAYSIZE(cmd_parm), p[Sel].SubKeyName); + } + else + { + StringCchCopy(cmd_file, ARRAYSIZE(cmd_file), _T("msiexec")); + StringCchCopy(cmd_parm, ARRAYSIZE(cmd_parm), szCode); + StringCchCat(cmd_parm, ARRAYSIZE(cmd_parm), p[Sel].SubKeyName); + } + } + else + { + if (pszString == NULL) + return 0; + // Для CreateProcess + StringCchCopy(cmd_line, ARRAYSIZE(cmd_line), pszString); + // Для ShellExecuteEx + if (LowPriority) + { + StringCchCopy(cmd_file, ARRAYSIZE(cmd_parm), _T("cmd")); + StringCchCopy(cmd_parm, ARRAYSIZE(cmd_parm), _T("/c start /low \"\" ")); + StringCchCat(cmd_parm, ARRAYSIZE(cmd_parm), pszString); + } + else + { + LPCTSTR psNextArg = NULL; + if (FirstArg(pszString, cmd_file, &psNextArg) + && IsFilePath(cmd_file)) + { + StringCchCopy(cmd_parm, ARRAYSIZE(cmd_parm), psNextArg); + } + else + { + StringCchCopy(cmd_file, ARRAYSIZE(cmd_file), pszString); + cmd_parm[0] = 0; + } + } + } + + hScreen = Info.SaveScreen(0,0,-1,-1); //Это необходимо сделать, т.к. после запущенных программ нужно обновить окно ФАРа + + BOOL ifCreate = FALSE, bElevationFailed = FALSE, bPriorityChanged = FALSE; + DWORD dwErr = 0; + + // MSI сам выполнит повышение прав когда потребуется + if (!p[Sel].WindowsInstaller && Opt.UseElevation && !IsUserAdmin()) + { + // Required elevation + SHELLEXECUTEINFO sei = {sizeof(SHELLEXECUTEINFO)}; + sei.fMask = SEE_MASK_NOCLOSEPROCESS; + sei.lpVerb = _T("runas"); + sei.lpFile = cmd_file; + sei.lpParameters = cmd_parm; + sei.nShow = LowPriority ? SW_MINIMIZE : SW_SHOWNORMAL; + ifCreate = ShellExecuteEx(&sei); + if (ifCreate) + pi.hProcess = sei.hProcess; + else + bElevationFailed = true; + } + + // Если Elevation не запускался + if (!ifCreate) + { + ifCreate = CreateProcess // Start the child process. + ( + NULL, // No module name (use command line). + cmd_line, // Command line. + NULL, // Process handle not inheritable. + NULL, // Thread handle not inheritable. + FALSE, // Set handle inheritance to FALSE. + LowPriority ? IDLE_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS, // Creation flags. + NULL, // Use parent's environment block. + NULL, // Use parent's starting directory. + &si, // Pointer to STARTUPINFO structure. + &pi // Pointer to PROCESS_INFORMATION structure. + ); + if (ifCreate) + bPriorityChanged = TRUE; + } + + if (!ifCreate) //not Create + { + dwErr = GetLastError(); + if ((dwErr == 0x2E4) && !bElevationFailed) + { + // Required elevation + SHELLEXECUTEINFO sei = {sizeof(SHELLEXECUTEINFO)}; + sei.fMask = SEE_MASK_NOCLOSEPROCESS; + sei.lpVerb = _T("runas"); + sei.lpFile = cmd_file; + sei.lpParameters = cmd_parm; + sei.nShow = LowPriority ? SW_MINIMIZE : SW_SHOWNORMAL; + ifCreate = ShellExecuteEx(&sei); + if (ifCreate) + pi.hProcess = sei.hProcess; + else + dwErr = GetLastError(); + } + if (!ifCreate) //not Create + { + TCHAR szErrCode[32]; + const TCHAR *pszErrInfo = szErrCode; + if (dwErr == 0x000004C7) + pszErrInfo = GetMsg(MCancelledByUser); + else + StringCchPrintf(szErrCode, ARRAYSIZE(szErrCode), _T("ErrorCode=0x%08X"), dwErr); + if (hScreen) + Info.RestoreScreen(hScreen); + DrawMessage(FMSG_WARNING, 1, "%s",GetMsg(MPlugIn),GetMsg(MRunProgErr),cmd_line,pszErrInfo,GetMsg(MBtnOk),NULL); + return -1; + } + } + + // -- не может, если был сделан Elevation, а если Elevation не было - то уже в CreateProcess + //if (pi.hProcess && LowPriority && !bPriorityChanged) + //{ + // bPriorityChanged = SetPriorityClass(pi.hProcess, IDLE_PRIORITY_CLASS); + // dwErr = GetLastError(); + //} + + TCHAR SaveTitle[MAX_PATH]; + GetConsoleTitle(SaveTitle,ARRAYSIZE(SaveTitle)); + SaveTitle[ARRAYSIZE(SaveTitle) - 1] = 0; + SetConsoleTitle(cmd_line); + + if (pi.hProcess) + { + // Wait until child process exits. + if ((Action == Action_UninstallWait) + || (Action == Action_ModifyWait) + || (Action == Action_RepairWait)) + { + DrawMessage(0, 0, "%s", GetMsg(MPlugIn), GetMsg(MWaitingCompletion), cmd_line,NULL); + nWaitSucceeded = 1; + while (true) + { + if (WaitForSingleObject(pi.hProcess, 500) == WAIT_OBJECT_0) + break; + if (CheckForEsc()) + { + nWaitSucceeded = 0; + break; + } + } + } + // Close process and thread handles. + CloseHandle(pi.hProcess); + } + if (pi.hThread) + CloseHandle(pi.hThread); + + SetConsoleTitle(SaveTitle); + + if (hScreen) + { + Info.RestoreScreen(NULL); + Info.RestoreScreen(hScreen); + } + return nWaitSucceeded; +} + +typedef WINADVAPI LSTATUS (APIENTRY *FRegDeleteKeyExA)(__in HKEY hKey, __in LPCSTR lpSubKey, __in REGSAM samDesired, __reserved DWORD Reserved); +typedef WINADVAPI LSTATUS (APIENTRY *FRegDeleteKeyExW)(__in HKEY hKey, __in LPCWSTR lpSubKey, __in REGSAM samDesired, __reserved DWORD Reserved); + +bool DeleteEntry(int Sel) +{ + HMODULE h_mod = LoadLibrary(_T("advapi32.dll")); + FRegDeleteKeyExA RegDeleteKeyExA = reinterpret_cast(GetProcAddress(h_mod, "RegDeleteKeyExA")); + FRegDeleteKeyExW RegDeleteKeyExW = reinterpret_cast(GetProcAddress(h_mod, "RegDeleteKeyExW")); + FreeLibrary(h_mod); + + HKEY userKey; + LONG ret = RegOpenKeyEx(p[Sel].RegKey.Root, p[Sel].RegKey.Path, 0, DELETE | p[Sel].RegView, &userKey); + if (ret != ERROR_SUCCESS) return false; + if (RegDeleteKeyEx) + ret = RegDeleteKeyEx(userKey, p[Sel].SubKeyName, p[Sel].RegView, 0); + else + ret = RegDeleteKey(userKey, p[Sel].SubKeyName); + RegCloseKey(userKey); + if (ret != ERROR_SUCCESS) return false; + return true; +} + +//сравнить строки +int __cdecl CompareEntries(const void* item1, const void* item2) +{ + return FSF.LStricmp(reinterpret_cast(item1)->Keys[DisplayName], reinterpret_cast(item2)->Keys[DisplayName]); +} +//сравнить даты +int __cdecl CompareEntriesDate(const void* item1, const void* item2) +{ + if (reinterpret_cast(item1)->InstDateN < reinterpret_cast(item2)->InstDateN) + return 1; + if (reinterpret_cast(item1)->InstDateN > reinterpret_cast(item2)->InstDateN) + return -1; + return CompareEntries(item1, item2); +} + +#define JUMPREALLOC 50 +void EnumKeys(RegKeyPath& RegKey, REGSAM RegView = 0) { + HKEY hKey; + if (RegOpenKeyEx(RegKey.Root, RegKey.Path, 0, KEY_READ | RegView, &hKey) != ERROR_SUCCESS) + return; + DWORD cSubKeys; + if (RegQueryInfoKey(hKey,NULL,NULL,NULL,&cSubKeys,NULL,NULL,NULL,NULL,NULL,NULL,NULL) != ERROR_SUCCESS) + return; + + TCHAR Buf[MAX_PATH]; + for (DWORD fEnumIndex=0; fEnumIndex= nRealCount) + { + nRealCount += JUMPREALLOC; + p = (KeyInfo *) realloc(p, sizeof(KeyInfo) * nRealCount); + } + if (FillReg(p[nCount], Buf, RegKey, RegView)) + { +#ifdef FARAPI17 + CharToOem(p[nCount].Keys[DisplayName], p[nCount].Keys[DisplayName]); + CharToOem(p[nCount].Keys[UninstallString], p[nCount].Keys[UninstallString]); + CharToOem(p[nCount].Keys[ModifyPath], p[nCount].Keys[ModifyPath]); +#endif + nCount++; + } + } + RegCloseKey(hKey); +} +#undef JUMPREALLOC + +typedef WINBASEAPI VOID (WINAPI *FGetNativeSystemInfo)(__out LPSYSTEM_INFO lpSystemInfo); + +#define EMPTYSTR _T(" ") +//Обновление информации +void UpDateInfo(void) +{ + HMODULE h_mod = LoadLibrary(_T("kernel32.dll")); + FGetNativeSystemInfo GetNativeSystemInfo = reinterpret_cast(GetProcAddress(h_mod, "GetNativeSystemInfo")); + FreeLibrary(h_mod); + bool is_os_x64 = false; + if (GetNativeSystemInfo) + { + SYSTEM_INFO si; + GetNativeSystemInfo(&si); + is_os_x64 = si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64; + } + + nCount = nRealCount = 0; + for (int i=0;i(FLI[i].Text); + + if (FirstChar[1] != FSF.LUpper(p[i].Keys[DisplayName][0])) + { + FirstChar[1] = FSF.LUpper(p[i].Keys[DisplayName][0]); + StringCchCopy(text, MaxSize, FirstChar); + } + else + StringCchCopy(text, MaxSize, EMPTYSTR); + + if (p[i].RegKey.Root == HKEY_LOCAL_MACHINE) + { + if (is_os_x64) + StringCchCat(text, MaxSize, (p[i].RegView == KEY_WOW64_64KEY) ? sx64 : sx86); + else + StringCchCat(text, MaxSize, sHKLM); + } + else + StringCchCat(text, MaxSize, sHKCU); + + StringCchCat(text, MaxSize, _T(" ")); + StringCchCat(text, MaxSize, p[i].InstDate); + StringCchCat(text, MaxSize, _T(" ")); + StringCchCat(text, MaxSize, (p[i].WindowsInstaller) ? _T("W") : _T(" ")); + StringCchCat(text, MaxSize, (p[i].CanModify) ? _T("M") : _T(" ")); + StringCchCat(text, MaxSize, (p[i].CanRepair) ? _T("R") : _T(" ")); + StringCchCat(text, MaxSize, (p[i].Hidden) ? _T("-") : _T(" ")); + StringCchCat(text, MaxSize, _T(" ")); + + //if ((p[i].Keys[ModifyPath][0] == 0) && (p[i].Keys[UninstallString][0] == 0)) + //if (p[i].Hidden) + // StringCchCat(text, MaxSize, _T(" - ")); + //else + // StringCchCat(text, MaxSize, _T(" ")); + + size_t nCurLen = _tcslen(text); + //StringCchCat(text, MaxSize, p[i].Keys[DisplayName]); + StringCchCopyN(text+nCurLen, MaxSize-nCurLen, p[i].Keys[DisplayName], MaxSize-nCurLen-1); + text[MaxSize-1] = 0; + } + + ListSize = nCount; +} +#undef EMPTYSTR + +//------------------------------------------------------------------- + +void ReadRegistry() +{ + //TechInfo + if (GetRegKey(HKCU,_T(""),_T("WhereWork"),Opt.WhereWork,3)) + if ((Opt.WhereWork<0) || (Opt.WhereWork>3)) + Opt.WhereWork=3; + SetRegKey(HKCU,_T(""),_T("WhereWork"),(DWORD) Opt.WhereWork); + + if (GetRegKey(HKCU,_T(""),_T("EnterAction"),Opt.EnterAction,Action_Menu)) + if ((Opt.EnterAction<0) || (Opt.EnterAction>Action_Menu)) + Opt.EnterAction = Action_Menu; + SetRegKey(HKCU,_T(""),_T("EnterAction"),(DWORD) Opt.EnterAction); + + if (GetRegKey(HKCU,_T(""),_T("ShiftEnterAction"),Opt.ShiftEnterAction,Action_UninstallWait)) + if ((Opt.ShiftEnterAction<0) || (Opt.ShiftEnterAction>Action_Menu)) + Opt.ShiftEnterAction = Action_Menu; + SetRegKey(HKCU,_T(""),_T("ShiftEnterAction"),(DWORD) Opt.ShiftEnterAction); + + if (GetRegKey(HKCU,_T(""),_T("UseElevation"),Opt.UseElevation,1)) + if ((Opt.UseElevation<0) || (Opt.UseElevation>1)) + Opt.UseElevation=1; + SetRegKey(HKCU,_T(""),_T("UseElevation"),(DWORD) Opt.UseElevation); + + if (GetRegKey(HKCU,_T(""),_T("RunLowPriority"),Opt.RunLowPriority,0)) + if ((Opt.RunLowPriority<0) || (Opt.RunLowPriority>1)) + Opt.RunLowPriority=0; + SetRegKey(HKCU,_T(""),_T("RunLowPriority"),(DWORD) Opt.RunLowPriority); + + if (GetRegKey(HKCU,_T(""),_T("ForceMsiUse"),Opt.ForceMsiUse,0)) + if ((Opt.ForceMsiUse<0) || (Opt.ForceMsiUse>1)) + Opt.ForceMsiUse=0; + SetRegKey(HKCU,_T(""),_T("ForceMsiUse"),(DWORD) Opt.ForceMsiUse); + + Opt.SortByDate = false; +} diff --git a/Uninstall/src/project.ini b/Uninstall/src/project.ini index 7c7d726..f06757a 100644 --- a/Uninstall/src/project.ini +++ b/Uninstall/src/project.ini @@ -2,4 +2,4 @@ MODULE = UnInstall VER_MAJOR = 1 VER_MINOR = 10 -VER_PATCH = 13 +VER_PATCH = 14