summaryrefslogtreecommitdiff
path: root/plugins/Ping
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-11-28 17:40:59 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-11-28 17:40:59 +0000
commit6e7708ae1760c85840f2e30e9af7221d2b149905 (patch)
tree05cb1aea34b3ecfd3b3729840766db1b722b7182 /plugins/Ping
parent5e9e63c45e37917ffb0acd83832d0d8f99d01883 (diff)
- Ping: folder rename
git-svn-id: http://svn.miranda-ng.org/main/trunk@2541 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/Ping')
-rw-r--r--plugins/Ping/collection.h834
-rw-r--r--plugins/Ping/common.h125
-rw-r--r--plugins/Ping/green.icobin0 -> 2550 bytes
-rw-r--r--plugins/Ping/grey.icobin0 -> 3438 bytes
-rw-r--r--plugins/Ping/icmp.cpp117
-rw-r--r--plugins/Ping/icmp.h71
-rw-r--r--plugins/Ping/log.cpp59
-rw-r--r--plugins/Ping/log.h12
-rw-r--r--plugins/Ping/menu.cpp98
-rw-r--r--plugins/Ping/menu.h10
-rw-r--r--plugins/Ping/options.cpp604
-rw-r--r--plugins/Ping/options.h26
-rw-r--r--plugins/Ping/ping.cpp179
-rw-r--r--plugins/Ping/ping.h41
-rw-r--r--plugins/Ping/ping.rc227
-rw-r--r--plugins/Ping/ping.vcxproj393
-rw-r--r--plugins/Ping/ping.vcxproj.filters121
-rw-r--r--plugins/Ping/pinggraph.cpp325
-rw-r--r--plugins/Ping/pinggraph.h22
-rw-r--r--plugins/Ping/pinglist.cpp230
-rw-r--r--plugins/Ping/pinglist.h26
-rw-r--r--plugins/Ping/pingthread.cpp1063
-rw-r--r--plugins/Ping/pingthread.h27
-rw-r--r--plugins/Ping/rawping.cpp217
-rw-r--r--plugins/Ping/rawping.h61
-rw-r--r--plugins/Ping/red.icobin0 -> 2550 bytes
-rw-r--r--plugins/Ping/resource.h80
-rw-r--r--plugins/Ping/utils.cpp374
-rw-r--r--plugins/Ping/utils.h35
-rw-r--r--plugins/Ping/yellow.icobin0 -> 2550 bytes
30 files changed, 5377 insertions, 0 deletions
diff --git a/plugins/Ping/collection.h b/plugins/Ping/collection.h
new file mode 100644
index 0000000000..f8709e3ef8
--- /dev/null
+++ b/plugins/Ping/collection.h
@@ -0,0 +1,834 @@
+#include <malloc.h>
+
+template<class T> class Collection {
+protected:
+ unsigned long count;
+public:
+ Collection(): count(0) {}
+
+ virtual void clear() = 0;
+ virtual void add(const T &val) = 0;
+ virtual const bool remove(const T &val) = 0;
+
+ const unsigned long size() const {return count;}
+};
+
+template<class T> class Node {
+public:
+ T val;
+
+ Node(const T &v): val(v) {}
+ virtual ~Node() {}
+};
+
+template<class T> class ListNode: public Node<T> {
+public:
+ ListNode<T> *next, *prev;
+
+ ListNode(const T &v): Node<T>(v), next(0), prev(0) {}
+ virtual ~ListNode() {
+ if(next) next->prev = prev;
+ if(prev) prev->next = next;
+ }
+};
+
+template<class T> class LinkedList: public Collection<T> {
+protected:
+ ListNode<T> *head, *tail;
+
+public:
+ class Iterator {
+ friend class LinkedList<T>;
+ protected:
+ ListNode<T> *n;
+ Iterator(ListNode<T> *start): n(start) {}
+ public:
+ Iterator(const Iterator &other): n(other.n) {}
+
+ virtual T &val() {return n->val;}
+ virtual void next() {if(n) n = n->next;}
+ virtual void prev() {if(n) n = n->prev;}
+ virtual const bool has_val() {return (n ? true : false); }
+ };
+
+ LinkedList(): Collection<T>(), head(0), tail(0) {};
+ LinkedList(const LinkedList<T> &other): Collection<T>(), head(0), tail(0) {
+ for(Iterator i = other.start(); i.has_val(); i.next())
+ add(i.val());
+ }
+ virtual ~LinkedList() {clear();}
+
+ LinkedList<T> &operator=(const LinkedList<T> &other) {
+ clear();
+ for(Iterator i = other.start(); i.has_val(); i.next())
+ add(i.val());
+ return *this;
+ }
+
+ virtual void clear() {
+ ListNode<T> *n;
+ while(head) {
+ n = head;
+ head = head->next;
+ delete n;
+ }
+ tail = 0;
+ Collection<T>::count = 0;
+ }
+
+ virtual Iterator start() const {return Iterator(head);}
+
+ virtual void add_front(T &val) {
+ ListNode<T> *n = new ListNode<T>(val);
+ n->next = head;
+ if(head) head->prev = n;
+ head = n;
+ if(!tail) tail = n;
+ Collection<T>::count++;
+ }
+
+ virtual void add(const T &val) {
+ ListNode<T> *n = new ListNode<T>(val);
+ n->prev = tail;
+ if(tail) tail->next = n;
+ tail = n;
+ if(!head) head = n;
+ Collection<T>::count++;
+ }
+
+ virtual const bool remove(const T &val) {
+ ListNode<T> *n = head;
+ while(n) {
+ if(n->val == val) {
+ if(n == head) head = head->next;
+ if(n == tail) tail = tail->prev;
+
+ delete n;
+ Collection<T>::count--;
+ return true;
+ } else
+ n = n->next;
+ }
+
+ return false;
+ }
+
+ virtual const bool contains(T &val) const {
+ ListNode<T> *n = head;
+ while(n) {
+ if(n->val == val) {
+ return true;
+ } else
+ n = n->next;
+ }
+
+ return false;
+ }
+
+ // queue/stack functions
+ // stack - use push/pop
+ // queue - use push_back/pop
+ virtual void push(T val) {
+ add_front(val);
+ }
+
+ virtual void push_back(T &val) {
+ add(val);
+ }
+
+ virtual const bool pop(T &val) {
+ if(!head) return false;
+
+ ListNode<T> *n = head;
+ if(head) {
+ head = head->next;
+ if(n == tail) tail = 0;
+ val = n->val;
+ delete n;
+ Collection<T>::count--;
+ return true;
+ } else
+ return false;
+ }
+};
+
+template<class T> class DynamicArray: public Collection<T> {
+protected:
+ T *ar;
+
+ unsigned long initial, limit, increment;
+
+public:
+ class Iterator {
+ friend class DynamicArray<T>;
+ protected:
+ T *ar;
+ unsigned long count;
+ unsigned long pos;
+ Iterator(T *a, const int c, unsigned long p): ar(a), count(c), pos(p) {}
+ public:
+ Iterator(const Iterator &other): ar(other.ar), count(other.count), pos(other.pos) {}
+
+ virtual T &val() {return ar[pos];}
+ virtual void next() {pos++;}
+ virtual void prev() {pos--;}
+ virtual const bool has_val() {return pos < count; }
+ };
+
+ DynamicArray(unsigned long init = 0, unsigned long inc = 1): Collection<T>(), ar(0), initial(init), limit(init), increment(inc) {
+ if(limit) ar = (T *)malloc(limit * sizeof(T));
+ }
+ virtual ~DynamicArray() {if(ar) free(ar);}
+
+ virtual void clear() {
+ Collection<T>::count = 0;
+ limit = initial;
+ if(limit) ar = (T *)realloc(ar, limit * sizeof(T));
+ else {
+ free(ar);
+ ar = 0;
+ }
+ }
+
+ virtual Iterator start() const {return Iterator(ar, Collection<T>::count, 0);}
+
+ virtual void add(const T &val) {
+ if(Collection<T>::count == limit) {
+ limit += increment;
+ ar = (T *)realloc(ar, limit * sizeof(T));
+ ar[Collection<T>::count++] = val;
+ } else
+ ar[Collection<T>::count++] = val;
+ }
+
+ virtual void add_all(DynamicArray<T> &other) {
+ for(Iterator i = other.start(); i.has_val(); i.next()) {
+ add(i.val());
+ }
+ }
+
+ virtual const bool remove(const T &val) {
+ for(unsigned long i = 0; i < Collection<T>::count; i++) {
+ if(ar[i] == val) {
+ memmove(ar + i, ar + i + 1, (Collection<T>::count - i) * sizeof(T));
+ Collection<T>::count--;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ virtual const bool remove(const unsigned long index) {
+ if(index >= Collection<T>::count) return false;
+
+ memmove(ar + index, ar + index + 1, (Collection<T>::count - index) * sizeof(T));
+ Collection<T>::count--;
+ return true;
+ }
+
+ virtual const bool insert(const T &val, const unsigned long index) {
+ if(index > Collection<T>::count) return false;
+
+ if(Collection<T>::count == limit) {
+ limit += increment;
+ ar = (T *)realloc(ar, limit * sizeof(T));
+ }
+
+ if(index < Collection<T>::count)
+ memmove(ar + index + 1, ar + index, (Collection<T>::count - index) * sizeof(T));
+
+ ar[index] = val;
+ Collection<T>::count++;
+ return true;
+ }
+
+ virtual T &operator[](const int index) {
+ return ar[index];
+ }
+
+ const bool index_of(const T &val, unsigned long &index) const {
+ for(int i = 0; i < Collection<T>::count; i++) {
+ if(ar[index] == val) {
+ index = i;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ const int index_of(const T &val) const {
+ for(int i = 0; i < Collection<T>::count; i++) {
+ if(ar[i] == val) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ // stack functions
+ virtual const bool pop(T &val) {
+ if(Collection<T>::count) {
+ val = ar[Collection<T>::count -1];
+ remove(Collection<T>::count -1);
+ return true;
+ }
+ return false;
+ }
+
+ virtual void push(const T &val) {
+ add(val);
+ }
+};
+
+template<class T> class SortedDynamicArray: public DynamicArray<T> {
+public:
+ SortedDynamicArray(unsigned long init = 0, unsigned long inc = 1): DynamicArray<T>(init, inc) {}
+ virtual ~SortedDynamicArray() {}
+
+ const bool get_index(const T &val, unsigned long &index) {
+ unsigned long low = 0;
+ unsigned long high = Collection<T>::count-1;
+
+ while( high < Collection<T>::count && low <= high )
+ {
+ unsigned long i = ( low+high )/2;
+ if ( DynamicArray<T>::ar[i] == val )
+ { index = i;
+ return true;
+ } else
+ if (DynamicArray<T>::ar[i] < val)
+ low = i+1;
+ else
+ high = i-1;
+ }
+
+ index = low;
+ return false;
+ }
+
+ virtual void add(const T &val) {
+ unsigned long index;
+ get_index(val, index);
+ insert(val, index);
+ }
+};
+
+template<class T> class TreeNode: public Node<T> {
+public:
+ TreeNode<T> *parent, *left, *right;
+
+ TreeNode(const T &v, TreeNode<T> *par): Node<T>(v), parent(par), left(0), right(0) {}
+ virtual ~TreeNode() {
+ if(parent) {
+ if(parent->left == this) parent->left = 0;
+ if(parent->right == this)parent->right = 0;
+ }
+ }
+};
+
+template<class T, class N = TreeNode<T> > class BinaryTree: public Collection<T> {
+protected:
+
+ N *root;
+
+ virtual void delete_node(N *n) {
+ if(n->left && n->right) {
+ N *minmax = n->left;
+ while(minmax->right) minmax = minmax->right;
+ n->val = minmax->val;
+ delete_node(minmax);
+ return;
+ } else if(n->right) {
+ if(n->parent) {
+ if(n->parent->left == n) n->parent->left = n->right;
+ else n->parent->right = n->right;
+ } else
+ root = n->right;
+ n->right->parent = n->parent;
+ } else if(n->left) {
+ if(n->parent) {
+ if(n->parent->left == n) n->parent->left = n->left;
+ else n->parent->right = n->left;
+ } else
+ root = n->left;
+ n->left->parent = n->parent;
+ } else {
+ if(n == root) root = 0;
+ }
+ delete n;
+ Collection<T>::count--;
+ }
+
+ virtual void insert_node(N *n) {
+ N *current = root, *parent = 0;
+ while(current) {
+ parent = current;
+ if(n->val < current->val)
+ current = current->left;
+ else
+ current = current->right;
+ }
+
+ if(parent) {
+ if(n->val < parent->val) {
+ parent->left = n;
+ } else {
+ parent->right = n;
+ }
+ } else
+ root = n;
+
+ n->parent = parent;
+ Collection<T>::count++;
+ }
+
+public:
+ class Iterator {
+ friend class BinaryTree<T, N>;
+ protected:
+
+ class EvalNode {
+ public:
+ bool evaluate;
+ N *node;
+
+ EvalNode(): evaluate(false), node(0) {}
+ EvalNode(const bool eval, N *n): evaluate(eval), node(n) {}
+ const bool operator==(const EvalNode &other) const {return node == other.node;}
+ EvalNode &operator=(const EvalNode &other) {evaluate = other.evaluate; node = other.node; return *this;}
+
+ };
+
+ N *n;
+ LinkedList<EvalNode> stack;
+
+
+ Iterator(N *start): n(0) {
+ if(start) {
+ stack.push(EvalNode(true, start));
+ next();
+ }
+ }
+
+ public:
+ Iterator(const Iterator &other):n(other.n), stack(other.stack) {}
+ virtual ~Iterator() {}
+
+ virtual T &val() {return n->val;}
+ virtual void next() {
+ EvalNode en;
+ bool popped = false;
+ while((popped = stack.pop(en)) && en.evaluate) {
+ if(en.node->right) stack.push(EvalNode(true, en.node->right));
+ stack.push(EvalNode(false, en.node));
+ if(en.node->left) stack.push(EvalNode(true, en.node->left));
+ }
+
+ n = (popped ? en.node : 0);
+ }
+ virtual const bool has_val() {return (n ? true : false);}
+ };
+
+ BinaryTree(): Collection<T>(), root(0) {};
+ BinaryTree(BinaryTree<T> &other): Collection<T>(), root(0) {
+ for(Iterator i = other.start(); i.has_val(); i.next())
+ add(i.val());
+ }
+ virtual ~BinaryTree() {clear();}
+
+ BinaryTree &operator=(BinaryTree<T> &other) {
+ clear();
+ for(Iterator i = other.start(); i.has_val(); i.next())
+ add(i.val());
+ return *this;
+ }
+
+ virtual void clear() {
+ N *current = root, *parent = 0;
+ while(current) {
+ if(current->left) current = current->left;
+ else if(current->right) current = current->right;
+ else {
+ parent = current->parent;
+ delete current;
+ current = parent;
+ }
+ }
+
+ root = 0;
+ Collection<T>::count = 0;
+ }
+
+ void add(const T &val) {
+ N *n = new N(val, 0);
+ insert_node(n);
+ }
+
+ const bool remove(const T &val) {
+ N *current = root;
+ while(current) {
+ if(current->val == val)
+ break;
+ else if(val < current->val)
+ current = current->left;
+ else
+ current = current->right;
+ }
+
+ if(current) {
+ delete_node(current);
+ return true;
+ }
+
+ return false;
+ }
+
+ const bool contains(const T &val) const {
+ N *current = root;
+ while(current) {
+ if(current->val == val)
+ break;
+ else if(val < current->val)
+ current = current->left;
+ else
+ current = current->right;
+ }
+
+ return current != 0;
+ }
+
+ Iterator start() const {return Iterator(root);}
+};
+
+#define RED 1
+#define BLACK 0
+
+// thanks to wikipedia (http://en.wikipedia.org/wiki/Red_black_tree)
+template<class T> class ColouredTreeNode: public Node<T> {
+public:
+ ColouredTreeNode<T> *parent, *left, *right;
+ char color;
+
+ ColouredTreeNode(const T &v, ColouredTreeNode<T> *par): Node<T>(v), parent(par), left(0), right(0), color(BLACK) {}
+ virtual ~ColouredTreeNode() {
+ if(parent) {
+ if(parent->left == this) parent->left = 0;
+ if(parent->right == this)parent->right = 0;
+ }
+ }
+};
+
+template<class T, class N = ColouredTreeNode<T> > class RedBlackTree: public BinaryTree<T, N> {
+protected:
+ N *grandparent(N *n) {
+ if (n && n->parent)
+ return n->parent->parent;
+ else
+ return NULL;
+ }
+ N *uncle(N *n) {
+ if(grandparent(n)) {
+ if (n->parent == grandparent(n)->left)
+ return grandparent(n)->right;
+ else
+ return grandparent(n)->left;
+ } else
+ return NULL;
+ }
+ N *sibling(N *n) {
+ if(n->parent) {
+ if (n == n->parent->left)
+ return n->parent->right;
+ else
+ return n->parent->left;
+ } else
+ return NULL;
+ }
+ bool is_leaf(N *n) {
+ return n == 0;
+ }
+
+ void replace_node(N *o, N *n) {
+ n->parent = o->parent;
+ if(n->parent) {
+ if(n->parent->left == o) n->parent->left = n;
+ else if(n->parent->right == o) n->parent->right = n;
+ } else
+ BinaryTree<T, N>::root = n;
+ }
+
+ void rotate_left(N *n) {
+ N *p = n->right;
+ N *q = n;
+
+ q->right = p->left;
+ if(q->right) q->right->parent = q;
+ p->left = q;
+ p->parent = q->parent;
+ q->parent = p;
+ if(p->parent) {
+ if(p->parent->left == q) p->parent->left = p;
+ else if(p->parent->right == q) p->parent->right = p;
+ } else
+ BinaryTree<T, N>::root = p;
+ }
+ void rotate_right(N *n) {
+ N *p = n->left;
+ N *q = n;
+
+ q->left = p->right;
+ if(q->left) q->left->parent = q;
+ p->right = q;
+ p->parent = q->parent;
+ q->parent = p;
+ if(p->parent) {
+ if(p->parent->left == q) p->parent->left = p;
+ else if(p->parent->right == q) p->parent->right = p;
+ } else
+ BinaryTree<T, N>::root = p;
+ }
+
+ void insert_case1(N *n) {
+ if (n->parent == NULL)
+ n->color = BLACK;
+ else
+ insert_case2(n);
+ }
+ void insert_case2(N *n) {
+ if (n->parent->color == BLACK)
+ return; /* Tree is still valid */
+ else
+ insert_case3(n);
+ }
+ void insert_case3(N *n) {
+ if (uncle(n) != NULL && uncle(n)->color == RED) {
+ n->parent->color = BLACK;
+ uncle(n)->color = BLACK;
+ grandparent(n)->color = RED;
+ insert_case1(grandparent(n));
+ } else
+ insert_case4(n);
+ }
+ void insert_case4(N *n) {
+ if (n == n->parent->right && n->parent == grandparent(n)->left) {
+ rotate_left(n->parent);
+ n = n->left;
+ } else if (n == n->parent->left && n->parent == grandparent(n)->right) {
+ rotate_right(n->parent);
+ n = n->right;
+ }
+ insert_case5(n);
+ }
+ void insert_case5(N *n) {
+ n->parent->color = BLACK;
+ grandparent(n)->color = RED;
+ if (n == n->parent->left && n->parent == grandparent(n)->left) {
+ rotate_right(grandparent(n));
+ } else {
+ /* Here, n == n->parent->right && n->parent == grandparent(n)->right */
+ rotate_left(grandparent(n));
+ }
+ }
+
+ void delete_case0(N *n) {
+ /* Precondition: n has at most one non-null child */
+ N *child = is_leaf(n->right) ? n->left : n->right;
+ if(child) replace_node(n, child);
+ if (n->color == BLACK) {
+ if(child) {
+ if (child->color == RED)
+ child->color = BLACK;
+ else
+ delete_case1(child);
+ } else
+ delete_case1(n);
+ }
+ if(BinaryTree<T, N>::root == n) BinaryTree<T, N>::root = 0;
+ delete n;
+ Collection<T>::count--;
+ }
+ void delete_case1(N *n) {
+ if (n->parent == NULL)
+ return;
+ else
+ delete_case2(n);
+ }
+ void delete_case2(N *n) {
+ if (sibling(n) && sibling(n)->color == RED) {
+ n->parent->color = RED;
+ sibling(n)->color = BLACK;
+ if (n == n->parent->left)
+ rotate_left(n->parent);
+ else
+ rotate_right(n->parent);
+ }
+ delete_case3(n);
+ }
+ void delete_case3(N *n) {
+ if (n->parent->color == BLACK &&
+ sibling(n) &&
+ sibling(n)->color == BLACK &&
+ (sibling(n)->left == 0 || sibling(n)->left->color == BLACK) &&
+ (sibling(n)->right == 0 || sibling(n)->right->color == BLACK))
+ {
+ sibling(n)->color = RED;
+ delete_case1(n->parent);
+ } else
+ delete_case4(n);
+ }
+ void delete_case4(N *n) {
+ if (n->parent->color == RED &&
+ sibling(n) &&
+ sibling(n)->color == BLACK &&
+ (sibling(n)->left == 0 || sibling(n)->left->color == BLACK) &&
+ (sibling(n)->right == 0 || sibling(n)->right->color == BLACK))
+ {
+ sibling(n)->color = RED;
+ n->parent->color = BLACK;
+ } else
+ delete_case5(n);
+ }
+ void delete_case5(N *n) {
+ if (n == n->parent->left &&
+ sibling(n) &&
+ sibling(n)->color == BLACK &&
+ sibling(n)->left &&
+ sibling(n)->left->color == RED &&
+ (sibling(n)->right == 0 || sibling(n)->right->color == BLACK))
+ {
+ sibling(n)->color = RED;
+ sibling(n)->left->color = BLACK;
+ rotate_right(sibling(n));
+ } else if (n == n->parent->right &&
+ sibling(n) &&
+ sibling(n)->color == BLACK &&
+ sibling(n)->right &&
+ sibling(n)->right->color == RED &&
+ (sibling(n)->left == 0 || sibling(n)->left->color == BLACK))
+ {
+ sibling(n)->color = RED;
+ sibling(n)->right->color = BLACK;
+ rotate_left(sibling(n));
+ }
+ delete_case6(n);
+ }
+ void delete_case6(N *n) {
+ sibling(n)->color = n->parent->color;
+ n->parent->color = BLACK;
+ if (n == n->parent->left) {
+ /* Here, sibling(n)->right->color == RED */
+ sibling(n)->right->color = BLACK;
+ rotate_left(n->parent);
+ } else {
+ /* Here, sibling(n)->left->color == RED */
+ sibling(n)->left->color = BLACK;
+ rotate_right(n->parent);
+ }
+ }
+
+ N *get_predecessor(N *n) {
+ N *minmax = n->left;
+ while(minmax->right) minmax = minmax->right;
+ return minmax;
+ }
+
+ virtual void insert_node(N *n) {
+ BinaryTree<T, N>::insert_node(n);
+ n->color = RED;
+
+ insert_case1(n);
+ }
+
+ virtual void delete_node(N *n) {
+ if(n->left && n->right) {
+ N *predecessor = get_predecessor(n);
+ n->val = predecessor->val;
+ delete_case0(predecessor);
+ } else
+ delete_case0(n);
+ }
+
+public:
+ RedBlackTree(): BinaryTree< T, N >() {}
+ virtual ~RedBlackTree() {}
+};
+
+template<class A, class B> class Pair {
+public:
+ A first;
+ B second;
+
+ Pair(const A &f): first(f) {}
+ Pair(const A &f, const B &s): first(f), second(s) {}
+ Pair(const Pair<A,B> &other): first(other.first), second(other.second) {}
+ virtual ~Pair() {}
+
+ const bool operator<(const Pair<A,B> &other) const {return first < other.first;}
+ const bool operator==(const Pair<A,B> &other) const {return first == other.first;}
+ Pair<A,B> &operator=(const Pair<A,B> &other) {first = other.first; second = other.second; return *this;}
+};
+
+//template<class A, class B, class N = TreeNode<Pair<A, B> > > class Map: public BinaryTree< Pair< A, B >, N > {
+template<class A, class B, class N = ColouredTreeNode<Pair<A, B> > > class Map: public RedBlackTree< Pair< A, B >, N > {
+protected:
+
+ N *find(A &key) const {
+ N *n = RedBlackTree< Pair< A, B >, N >::root;
+ while(n) {
+ if(n->val.first == key)
+ return n;
+ else if(key < n->val.first)
+ n = n->left;
+ else
+ n = n->right;
+
+ }
+ return 0;
+ }
+public:
+ //Map(): BinaryTree< Pair<A,B>, N >() {}
+ Map(): RedBlackTree< Pair<A,B>, N >() {}
+ virtual ~Map() {}
+
+ void put(A &key, B &value) {
+ add(Pair<A,B>(key, value));
+ }
+
+ const bool get(A &key, B &val) const {
+ const N *n = find(key);
+ if(n) {
+ val = n->val.second;
+ return true;
+ } else
+ return false;
+ }
+
+ B &operator[](A &key) {
+ N *n = find(key);
+ if(n)
+ return n->val.second;
+ else {
+ Pair< A, B > p(key);
+ N *n = new N(p, 0);
+ insert_node(n);
+ return n->val.second;
+ }
+ }
+
+ virtual const bool exists(A &key) const {
+ const N *n = find(key);
+ if(n) {
+ return true;
+ } else
+ return false;
+ }
+
+ virtual const bool remove(A &key) {
+ N *n = find(key);
+ if(n) {
+ delete_node(n);
+ return true;
+ } else
+ return false;
+ }
+};
diff --git a/plugins/Ping/common.h b/plugins/Ping/common.h
new file mode 100644
index 0000000000..cc014898e1
--- /dev/null
+++ b/plugins/Ping/common.h
@@ -0,0 +1,125 @@
+#ifndef _COMMON_H
+#define _COMMON_H
+
+#define MAX_HISTORY (1440) // 12 hrs at 30 sec intervals
+
+#define PLUG "PING"
+
+#define DEFAULT_PING_PERIOD 30
+#define DEFAULT_PING_TIMEOUT 2
+#define DEFAULT_SHOW_POPUP true
+#define DEFAULT_SHOW_POPUP2 false
+#define DEFAULT_BLOCK_REPS true
+#define DEFAULT_LOGGING_ENABLED false
+#define DEFAULT_LOG_FILENAME "ping_log.txt"
+#define DEFAULT_NO_TEST_ICON true
+#define DEFAULT_ATTACH_TO_CLIST false
+
+#define MAX_PINGADDRESS_STRING_LENGTH 256
+
+//#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+//#define VC_EXTRALEAN
+//#define _WIN32_WINNT 0x0500
+
+#define WINVER 0x0500
+#define _WIN32_WINNT 0x0500
+#define _WIN32_IE 0x0300
+
+#define MIRANDA_VER 0x0600
+#include <windows.h>
+
+//#include <prsht.h>
+#include <shellapi.h>
+#include <commdlg.h>
+#include <commctrl.h>
+#include <time.h>
+
+#include <stdio.h>
+
+#include <newpluginapi.h>
+#include <statusmodes.h>
+#include <m_options.h>
+#include <m_langpack.h>
+#include <m_popup.h>
+#include <m_system.h>
+#include <m_skin.h>
+#include <m_netlib.h>
+#include <m_database.h>
+#include <m_protocols.h>
+#include <m_protomod.h>
+#include <m_protosvc.h>
+#include <m_ignore.h>
+#include <m_clist.h>
+#include <m_clui.h>
+#include <m_genmenu.h>
+#include <m_cluiframes.h>
+#include <m_utils.h>
+#include <m_fontservice.h>
+#include <m_icolib.h>
+
+
+#include "collection.h"
+
+typedef struct {
+ int ping_period, ping_timeout;
+ bool show_popup, show_popup2, block_reps, logging;
+ char log_filename[MAX_PATH];
+ bool no_test_icon;
+ int row_height;
+ int indent;
+ int retries;
+ bool attach_to_clist;
+ bool log_csv;
+} PingOptions;
+
+#pragma warning( disable : 4786 )
+
+// a deque of pairs - ping time and timestamp
+struct HistPair {
+ short first;
+ time_t second;
+
+ const bool operator==(const HistPair &other) const {return first == other.first && second == other.second;}
+};
+typedef LinkedList< HistPair > HistoryList;
+
+
+#define PS_RESPONDING 1
+#define PS_NOTRESPONDING 2
+#define PS_TESTING 3
+#define PS_DISABLED 4
+
+struct PINGADDRESS {
+ int cbSize; //size in bytes of this structure
+ DWORD item_id;
+ char pszName[MAX_PINGADDRESS_STRING_LENGTH]; //IP address or domain name
+ char pszLabel[MAX_PINGADDRESS_STRING_LENGTH];
+ bool responding;
+ int status;
+ short round_trip_time;
+ int miss_count;
+ int port; // -1 for ICMP, non-zero for TCP
+ char pszProto[MAX_PINGADDRESS_STRING_LENGTH];
+ char pszCommand[MAX_PATH];
+ char pszParams[MAX_PATH];
+ unsigned int get_status; // on success, if status equals this
+ unsigned int set_status; // set it to this
+ int index;
+
+ const bool operator==(const PINGADDRESS &b) const;
+ const bool operator<(const PINGADDRESS &b) const;
+};
+
+typedef Map<DWORD, HistoryList> HistoryMap;
+
+
+extern HANDLE hNetlibUser;
+extern HINSTANCE hInst;
+
+extern bool use_raw_ping;
+
+#ifndef MIID_PING
+#define MIID_PING {0x9cd1684e, 0xc520, 0x4b58, { 0x9a, 0x52, 0xae, 0x3d, 0x7a, 0x72, 0x4, 0x46}}
+#endif
+
+#endif
diff --git a/plugins/Ping/green.ico b/plugins/Ping/green.ico
new file mode 100644
index 0000000000..82ce348616
--- /dev/null
+++ b/plugins/Ping/green.ico
Binary files differ
diff --git a/plugins/Ping/grey.ico b/plugins/Ping/grey.ico
new file mode 100644
index 0000000000..7b91f7a64d
--- /dev/null
+++ b/plugins/Ping/grey.ico
Binary files differ
diff --git a/plugins/Ping/icmp.cpp b/plugins/Ping/icmp.cpp
new file mode 100644
index 0000000000..af9a3605e4
--- /dev/null
+++ b/plugins/Ping/icmp.cpp
@@ -0,0 +1,117 @@
+#include "common.h"
+#include "icmp.h"
+
+char data[] = "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHH";
+ICMP *ICMP::instance = 0;
+
+#define BUFFER_SIZE (8 * (sizeof(ICMP_ECHO_REPLY) + sizeof(data)))
+
+ICMP::ICMP():
+ timeout(2000),
+ functions_loaded(false)
+{
+ hDLL = LoadLibrary(_T("IPHLPAPI.DLL"));
+ if(hDLL) {
+ pIcmpCreateFile = (pfnHV)GetProcAddress(hDLL, "IcmpCreateFile");
+ pIcmpCloseHandle = (pfnBH)GetProcAddress(hDLL, "IcmpCloseHandle");
+ pIcmpSendEcho2 = (pfnDHDPWPipPDD)GetProcAddress(hDLL, "IcmpSendEcho2");
+ }
+ if (hDLL == 0 || pIcmpCreateFile == 0 || pIcmpCloseHandle == 0 || pIcmpSendEcho2 == 0) {
+ hDLL = LoadLibrary(_T("ICMP.DLL"));
+ if(hDLL) {
+ pIcmpCreateFile = (pfnHV)GetProcAddress(hDLL, "IcmpCreateFile");
+ pIcmpCloseHandle = (pfnBH)GetProcAddress(hDLL, "IcmpCloseHandle");
+ pIcmpSendEcho2 = (pfnDHDPWPipPDD)GetProcAddress(hDLL, "IcmpSendEcho2");
+ }
+ if (hDLL == 0 || pIcmpCreateFile == 0 || pIcmpCloseHandle == 0 || pIcmpSendEcho2 == 0)
+ return;
+ else
+ DBWriteContactSettingString(0, PLUG, "PingLib", "ICMP.DLL"); // for debugging
+ } else
+ DBWriteContactSettingString(0, PLUG, "PingLib", "IPHLPAPI.DLL"); // for debugging
+
+ WSAData wsaData;
+ if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
+ WSACleanup();
+ FreeLibrary((HMODULE)hDLL);
+ return;
+ }
+
+ /*
+ hIP = pIcmpCreateFile();
+ if (hIP == INVALID_HANDLE_VALUE) {
+ pIcmpCloseHandle(hIP);
+ return;
+ }
+ */
+
+ buff = new char[BUFFER_SIZE];
+ functions_loaded = true;
+}
+
+void ICMP::stop() {
+ //if(hIP) {
+ // pIcmpCloseHandle(hIP);
+ // hIP = 0;
+ //}
+}
+
+ICMP::~ICMP() {
+ if(hIP) stop();
+ WSACleanup();
+ if(hDLL)
+ FreeLibrary(hDLL);
+ delete[] buff;
+}
+
+bool ICMP::ping(char *host, ICMP_ECHO_REPLY &reply) {
+ if(!functions_loaded) return false;
+
+ HOSTENT *rec;
+ IP_OPTION_INFORMATION ipoi;
+
+ unsigned long address = inet_addr(host);
+ if (address == INADDR_NONE) {
+ rec = gethostbyname(host);
+ if(rec) address = *(unsigned long *)(*rec->h_addr_list);
+ else return false;
+ }
+
+ ipoi.Ttl = 255;
+ ipoi.Tos = 0;
+ ipoi.Flags = 0;
+ ipoi.OptionsSize = 0;
+ ipoi.OptionsData = 0;
+
+ reply.Status = 0;
+
+ hIP = pIcmpCreateFile();
+ if (hIP == INVALID_HANDLE_VALUE) return false;
+
+ //pIcmpSendEcho2(hIP, 0, 0, 0, address, data, sizeof(data), &ipoi, buff, sizeof(ICMP_ECHO_REPLY) + sizeof(data), timeout);
+ if(pIcmpSendEcho2(hIP, 0, 0, 0, address, data, sizeof(data), 0, buff, BUFFER_SIZE, timeout) == 0) {
+ DWORD code = GetLastError();
+ if(code != 11010) {
+ char winmsg[512], msg[1024];
+ FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, code, 0, winmsg, 512, 0);
+ mir_snprintf(msg, 1024, "Ping error (%d): %s", code, winmsg);
+ PUShowMessage(msg, SM_NOTIFY);
+ return false;
+ }
+ }
+ memcpy(&reply, buff, sizeof(ICMP_ECHO_REPLY));
+
+ pIcmpCloseHandle(hIP);
+
+ return (reply.Status == 0);
+}
+
+ICMP *ICMP::get_instance() {
+ if(!instance)
+ instance = new ICMP();
+ return instance;
+}
+
+void ICMP::cleanup() {
+ if(instance) delete instance;
+} \ No newline at end of file
diff --git a/plugins/Ping/icmp.h b/plugins/Ping/icmp.h
new file mode 100644
index 0000000000..984fd88fe9
--- /dev/null
+++ b/plugins/Ping/icmp.h
@@ -0,0 +1,71 @@
+// adapted 23/9/2004 from public domain code at http://tangentsoft.net/wskfaq/examples/dllping.html
+
+#ifndef _ICMP_H
+#define _ICMP_H
+
+//#include <windows.h>
+#include <iphlpapi.h>
+//#include <icmpapi.h>
+
+// Structures required to use functions in ICMP.DLL
+/*
+typedef struct {
+ unsigned char Ttl; // Time To Live
+ unsigned char Tos; // Type Of Service
+ unsigned char Flags; // IP header flags
+ unsigned char OptionsSize; // Size in bytes of options data
+ unsigned char *OptionsData; // Pointer to options data
+} IP_OPTION_INFORMATION, * PIP_OPTION_INFORMATION;
+
+typedef struct {
+ DWORD Address; // Replying address
+ unsigned long Status; // Reply status
+ unsigned long RoundTripTime; // RTT in milliseconds
+ unsigned short DataSize; // Echo data size
+ unsigned short Reserved; // Reserved for system use
+ void *Data; // Pointer to the echo data
+ IP_OPTION_INFORMATION Options; // Reply options
+ unsigned char ReplyData[8];
+} IP_ECHO_REPLY, * PIP_ECHO_REPLY;
+
+*/
+typedef HANDLE (WINAPI* pfnHV)(VOID);
+typedef BOOL (WINAPI* pfnBH)(HANDLE);
+typedef DWORD (WINAPI* pfnDHDPWPipPDD)(HANDLE, HANDLE, FARPROC, PVOID, IPAddr, LPVOID, WORD, PIP_OPTION_INFORMATION, LPVOID, DWORD, DWORD);
+
+class ICMP {
+protected:
+ pfnHV pIcmpCreateFile;
+ pfnBH pIcmpCloseHandle;
+ pfnDHDPWPipPDD pIcmpSendEcho2;
+
+ HMODULE hDLL;
+
+ HANDLE hIP;
+
+ unsigned int timeout;
+ bool functions_loaded;
+
+ // protected constructor - singleton class
+ ICMP();
+ static ICMP *instance;
+
+ char *buff;
+
+public:
+ ~ICMP();
+ static ICMP *get_instance();
+ static void cleanup();
+
+ bool ping(char *host, ICMP_ECHO_REPLY &reply);
+
+ void set_timeout(unsigned int t) {
+ timeout = t;
+ }
+
+ void stop();
+
+ unsigned int get_timeout() {return timeout;}
+
+};
+#endif //_ICMP_H
diff --git a/plugins/Ping/log.cpp b/plugins/Ping/log.cpp
new file mode 100644
index 0000000000..de2889fde1
--- /dev/null
+++ b/plugins/Ping/log.cpp
@@ -0,0 +1,59 @@
+#include "common.h"
+#include "log.h"
+
+INT_PTR Log(WPARAM wParam, LPARAM lParam) {
+
+ TCHAR buf[1024], tbuf[512], dbuf[512];
+ CallService(PLUG "/GetLogFilename", (WPARAM)1024, (LPARAM)buf);
+
+ //char TBcapt[255];
+ SYSTEMTIME systime;
+
+ GetLocalTime(&systime);
+
+ GetTimeFormat(LOCALE_USER_DEFAULT, 0, &systime, 0, tbuf, 512);
+ GetDateFormat(LOCALE_USER_DEFAULT, 0, &systime, 0, dbuf, 512);
+
+ char *line = (char *)wParam;
+
+ FILE *f = _tfopen(buf, _T("a+"));
+ if(f) {
+ if(options.log_csv) {
+ fprintf(f, "%s, %s, %s\n", dbuf, tbuf, line);
+ } else {
+ fprintf(f, "%s, %s: %s\n", dbuf, tbuf, line);
+ }
+ fclose(f);
+ }
+
+ return 0;
+}
+
+INT_PTR GetLogFilename(WPARAM wParam, LPARAM lParam) {
+ DBVARIANT dbv;
+ char *filename = (char *)lParam;
+ if(DBGetContactSetting(0, PLUG, "LogFilename", &dbv)) {
+ CallService(MS_DB_GETPROFILEPATH, (WPARAM)wParam, (LPARAM)filename);
+ strcat(filename, "\\");
+ strcat(filename, "ping_log.txt");
+ } else {
+ strncpy(filename, dbv.pszVal, wParam);
+ DBFreeVariant(&dbv);
+ }
+
+ ((char *)lParam)[wParam - 1] = 0;
+
+ return 0;
+}
+
+INT_PTR SetLogFilename(WPARAM wParam, LPARAM lParam) {
+ DBWriteContactSettingString(0, PLUG, "LogFilename", (char *)lParam);
+ return 0;
+}
+
+INT_PTR ViewLogData(WPARAM wParam, LPARAM lParam) {
+ char buf[1024];
+ CallService(PLUG "/GetLogFilename", (WPARAM)MAX_PATH, (LPARAM)buf);
+ return (INT_PTR)ShellExecute((HWND)wParam, _T("edit"), buf, _T(""), _T(""), SW_SHOW);
+}
+
diff --git a/plugins/Ping/log.h b/plugins/Ping/log.h
new file mode 100644
index 0000000000..8fed816122
--- /dev/null
+++ b/plugins/Ping/log.h
@@ -0,0 +1,12 @@
+#ifndef _PING_LOG
+#define _PING_LOG
+
+#pragma warning( disable : 4786 )
+#include "options.h"
+
+INT_PTR Log(WPARAM wParam, LPARAM lParam);
+INT_PTR GetLogFilename(WPARAM wParam, LPARAM lParam);
+INT_PTR SetLogFilename(WPARAM wParam, LPARAM lParam);
+INT_PTR ViewLogData(WPARAM wParam, LPARAM lParam);
+
+#endif
diff --git a/plugins/Ping/menu.cpp b/plugins/Ping/menu.cpp
new file mode 100644
index 0000000000..dbec0a3447
--- /dev/null
+++ b/plugins/Ping/menu.cpp
@@ -0,0 +1,98 @@
+#include "common.h"
+#include "menu.h"
+
+HANDLE hMenuDisable, hMenuGraph, hMenuEdit;
+HANDLE hEventMenuBuild;
+
+/*
+int MenuBuild(WPARAM wParam, LPARAM lParam) {
+ CLISTMENUITEM menu;
+ ZeroMemory(&menu,sizeof(menu));
+ menu.cbSize=sizeof(menu);
+
+ menu.flags = CMIM_NAME | CMIM_ICON;
+ bool disable = DBGetContactSettingWord((HANDLE)wParam, PLUG, "Status", ID_STATUS_OFFLINE) != options.off_status;
+ if(disable) {
+ menu.hIcon = hIconDisabled;
+ menu.pszName = Translate("Disable");
+ } else {
+ menu.hIcon = hIconEnabled;
+ menu.pszName = Translate("Enable");
+ }
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuDisable, (LPARAM)&menu);
+
+ // hide graph menu item if window displayed
+ //menu.flags = CMIM_FLAGS | (DBGetContactSettingDword((HANDLE)wParam, PLUG, "WindowHandle", 0) == 0 ? 0 : CMIF_HIDDEN);
+ //CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuGraph, (LPARAM)&menu);
+
+ return 0;
+}
+*/
+
+void InitMenus() {
+
+ CLISTMENUITEM menu;
+ ZeroMemory(&menu,sizeof(menu));
+ menu.cbSize=sizeof(menu);
+
+ // main menu
+ menu.flags = CMIF_TCHAR;
+ menu.popupPosition = 500099900;
+ menu.ptszPopupName = LPGENT("PING");
+ menu.cbSize = sizeof( menu );
+ menu.position = 2000060000;
+ menu.hIcon = hIconResponding;
+ menu.ptszName = LPGENT("Enable All Pings");
+ menu.pszService = PLUG "/EnableAll";
+ Menu_AddMainMenuItem(&menu);
+
+ menu.popupPosition = 500299901;
+ menu.cbSize = sizeof( menu );
+ menu.position = 2000060001;
+ menu.popupPosition = 0;
+ menu.hIcon = hIconDisabled;
+ menu.ptszName = LPGENT("Disable All Pings");
+ menu.pszService = PLUG "/DisableAll";
+ Menu_AddMainMenuItem(&menu);
+
+ /*
+ // list items
+ menu.flags = 0;
+ menu.popupPosition = 0;
+ menu.pszPopupName = 0;
+ menu.cbSize = sizeof( menu );
+ menu.position =-300100;
+ //menu.popupPosition = 0;
+ menu.hIcon = hIconDisabled;
+ menu.pszName = Translate( "Disable" );
+ menu.pszService = PLUG "/ToggleEnabled";
+ menu.pszContactOwner = PLUG;
+ hMenuDisable = (HANDLE)CallService( MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&menu );
+
+ menu.flags = 0;
+ menu.popupPosition = 0;
+ menu.pszPopupName = 0;
+ menu.cbSize = sizeof( menu );
+ menu.position =-300090;
+ //menu.popupPosition = 0;
+ menu.hIcon = hIconResponding
+ menu.pszName = Translate( "Graph" );
+ menu.pszService = PLUG "/ShowGraph";
+ menu.pszContactOwner = PLUG;
+ hMenuGraph = (HANDLE)CallService( MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&menu );
+
+ menu.flags = 0;
+ menu.popupPosition = 0;
+ menu.pszPopupName = 0;
+ menu.cbSize = sizeof( menu );
+ menu.position =-300080;
+ //menu.popupPosition = 0;
+ menu.hIcon = hIconResponding;
+ menu.pszName = Translate( "Edit..." );
+ menu.pszService = PLUG "/Edit";
+ menu.pszContactOwner = PLUG;
+ hMenuGraph = (HANDLE)CallService( MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&menu );
+
+ hEventMenuBuild = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, MenuBuild);
+ */
+}
diff --git a/plugins/Ping/menu.h b/plugins/Ping/menu.h
new file mode 100644
index 0000000000..e6e1334885
--- /dev/null
+++ b/plugins/Ping/menu.h
@@ -0,0 +1,10 @@
+#ifndef _MENU_H
+#define _MENU_H
+
+#include "pinglist.h"
+#include "pinggraph.h"
+#include "utils.h"
+
+void InitMenus();
+
+#endif
diff --git a/plugins/Ping/options.cpp b/plugins/Ping/options.cpp
new file mode 100644
index 0000000000..1d19a67ded
--- /dev/null
+++ b/plugins/Ping/options.cpp
@@ -0,0 +1,604 @@
+#include "common.h"
+#include "options.h"
+
+PingOptions options;
+
+// main ping options
+static INT_PTR CALLBACK DlgProcOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HWND hw;
+ OPENFILENAME ofn = {0};
+
+ switch ( msg ) {
+ case WM_INITDIALOG: {
+ TranslateDialogDefault( hwndDlg );
+
+ if(ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) {
+ hw = GetDlgItem(hwndDlg, IDC_CHK_ATTACH);
+ EnableWindow(hw, FALSE);
+ }
+ CheckDlgButton(hwndDlg, IDC_CHK_ATTACH, options.attach_to_clist);
+
+ SetDlgItemInt(hwndDlg, IDC_PPM, options.ping_period, FALSE);
+ SetDlgItemInt(hwndDlg, IDC_PT, options.ping_timeout, FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHECKPOPUP, options.show_popup);
+ CheckDlgButton(hwndDlg, IDC_CHECKPOPUP2, options.show_popup2);
+ CheckDlgButton(hwndDlg, IDC_CHK_BLOCK, options.block_reps);
+ CheckDlgButton(hwndDlg, IDC_CHK_LOG, options.logging);
+ CheckDlgButton(hwndDlg, IDC_CHK_LOGCSV, options.log_csv);
+ CheckDlgButton(hwndDlg, IDC_CHK_NOTESTICON, options.no_test_icon);
+
+ SendMessage(GetDlgItem(hwndDlg, IDC_SP_INDENT), UDM_SETRANGE, 0, (LPARAM)MAKELONG(500, 0));
+ SendMessage(GetDlgItem(hwndDlg, IDC_SP_INDENT), UDM_SETPOS, 0, options.indent);
+ SendMessage(GetDlgItem(hwndDlg, IDC_SP_ROWHEIGHT), UDM_SETRANGE, 0, (LPARAM)MAKELONG(500, 6));
+ SendMessage(GetDlgItem(hwndDlg, IDC_SP_ROWHEIGHT), UDM_SETPOS, 0, options.row_height);
+
+ SetDlgItemInt(hwndDlg, IDC_RPT, options.retries, FALSE);
+
+ SetDlgItemText(hwndDlg, IDC_ED_FILENAME, options.log_filename);
+ if(!options.logging) {
+ hw = GetDlgItem(hwndDlg, IDC_ED_FILENAME);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_BTN_LOGBROWSE);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_LOGCSV);
+ EnableWindow(hw, FALSE);
+ }
+
+ if(!ServiceExists( MS_POPUP_ADDPOPUP )) {
+ hw = GetDlgItem(hwndDlg, IDC_CHECKPOPUP);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_CHECKPOPUP2);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_BLOCK);
+ EnableWindow(hw, FALSE);
+ }
+ return TRUE;
+ }
+ case WM_COMMAND:
+ if ( HIWORD( wParam ) == EN_CHANGE && ( HWND )lParam == GetFocus()) {
+ switch( LOWORD( wParam )) {
+ case IDC_PPM:
+ case IDC_PT:
+ case IDC_ED_FILENAME:
+ case IDC_RPT:
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ break;
+ }
+
+ if (HIWORD( wParam ) == CBN_SELCHANGE) {
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ break;
+ }
+
+ if ( HIWORD( wParam ) == BN_CLICKED ) {
+ switch( LOWORD( wParam )) {
+ case IDC_CHK_LOG:
+ hw = GetDlgItem(hwndDlg, IDC_ED_FILENAME);
+ EnableWindow(hw, IsDlgButtonChecked(hwndDlg, IDC_CHK_LOG));
+ hw = GetDlgItem(hwndDlg, IDC_BTN_LOGBROWSE);
+ EnableWindow(hw, IsDlgButtonChecked(hwndDlg, IDC_CHK_LOG));
+ hw = GetDlgItem(hwndDlg, IDC_CHK_LOGCSV);
+ EnableWindow(hw, IsDlgButtonChecked(hwndDlg, IDC_CHK_LOG));
+ // drop through
+ case IDC_CHK_LOGCSV:
+ case IDC_CHECKPOPUP:
+ case IDC_CHECKPOPUP2:
+ case IDC_CHK_BLOCK:
+ case IDC_CHK_MINMAX:
+ case IDC_CHK_NOTESTICON:
+ case IDC_CHK_ATTACH:
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_BTN_VIEWLOG:
+ CallService(PLUG "/ViewLogData", 0, 0);
+ break;
+ case IDC_BTN_LOGBROWSE:
+ ofn.lStructSize = sizeof(ofn);
+ ofn.lpstrFile = options.log_filename;
+ ofn.hwndOwner = hwndDlg;
+ ofn.Flags = CC_FULLOPEN;
+ //ofn.lpstrFile[0] = '\0';
+ ofn.nMaxFile = sizeof(options.log_filename);
+ ofn.lpstrFilter = _T("All\0*.*\0Text\0*.TXT\0");
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFileTitle = NULL;
+ ofn.nMaxFileTitle = 0;
+ ofn.lpstrInitialDir = NULL;
+ ofn.Flags = OFN_PATHMUSTEXIST;
+
+ if(GetOpenFileName(&ofn) == TRUE) {
+ SetDlgItemText(hwndDlg, IDC_ED_FILENAME, ofn.lpstrFile);
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ if (((LPNMHDR)lParam)->code == UDN_DELTAPOS ) {
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+ if (((LPNMHDR)lParam)->code == PSN_APPLY ) {
+
+ BOOL trans_success;
+
+ DWORD new_ping_period = GetDlgItemInt( hwndDlg, IDC_PPM, &trans_success, FALSE);
+ if(trans_success) {
+ options.ping_period = new_ping_period;
+ }
+ DWORD new_ping_timeout = GetDlgItemInt( hwndDlg, IDC_PT, &trans_success, FALSE);
+ if(trans_success) {
+ options.ping_timeout = new_ping_timeout;
+ }
+ options.show_popup = IsDlgButtonChecked(hwndDlg, IDC_CHECKPOPUP) == BST_CHECKED;
+ options.show_popup2 = IsDlgButtonChecked(hwndDlg, IDC_CHECKPOPUP2) == BST_CHECKED;
+ options.block_reps = IsDlgButtonChecked(hwndDlg, IDC_CHK_BLOCK) == BST_CHECKED;
+ options.logging = IsDlgButtonChecked(hwndDlg, IDC_CHK_LOG) == BST_CHECKED;
+ options.log_csv = IsDlgButtonChecked(hwndDlg, IDC_CHK_LOGCSV) == BST_CHECKED;
+ GetDlgItemText(hwndDlg, IDC_ED_FILENAME, options.log_filename, MAX_PATH);
+
+ options.no_test_icon = IsDlgButtonChecked(hwndDlg, IDC_CHK_NOTESTICON) == BST_CHECKED;
+
+ options.indent = SendMessage(GetDlgItem(hwndDlg, IDC_SP_INDENT), UDM_GETPOS, 0, 0);
+ options.row_height = SendMessage(GetDlgItem(hwndDlg, IDC_SP_ROWHEIGHT), UDM_GETPOS, 0, 0);
+
+ DWORD new_retries = GetDlgItemInt( hwndDlg, IDC_RPT, &trans_success, FALSE);
+ if(trans_success) {
+ options.retries = new_retries;
+ }
+
+ bool new_attach = (IsDlgButtonChecked(hwndDlg, IDC_CHK_ATTACH) == BST_CHECKED);
+ if(!ServiceExists(MS_CLIST_FRAMES_ADDFRAME) && options.attach_to_clist != new_attach)
+ AttachToClist(new_attach);
+
+ options.attach_to_clist = new_attach;
+
+ SaveOptions();
+
+ RefreshWindow(0, 0);
+
+ if(options.logging) CallService(PLUG "/Log", (WPARAM)"options changed", 0);
+ if(hWakeEvent) SetEvent(hWakeEvent);
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+PINGLIST temp_list;
+PINGADDRESS add_edit_addr;
+
+// host edit
+INT_PTR CALLBACK DlgProcDestEdit(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
+ HWND hw;
+ int sel;
+ char *strptr;
+
+ switch ( msg ) {
+ case WM_INITDIALOG:
+ {
+ for(int i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) {
+ strptr = (char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM)i, (LPARAM)0);
+ hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTSTAT);
+ SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)strptr);
+ hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTSTAT2);
+ SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)strptr);
+ }
+
+ hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTSTAT);
+ SendMessage(hw, CB_SETCURSEL, 1, 0);
+ hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTSTAT2);
+ SendMessage(hw, CB_SETCURSEL, 0, 0);
+
+ SetDlgItemText(hwndDlg, IDC_ED_DESTADDR, add_edit_addr.pszName);
+ SetDlgItemText(hwndDlg, IDC_ED_DESTLAB, add_edit_addr.pszLabel);
+ SetDlgItemText(hwndDlg, IDC_ED_COMMAND, add_edit_addr.pszCommand);
+ SetDlgItemText(hwndDlg, IDC_ED_PARAMS, add_edit_addr.pszParams);
+
+ CheckDlgButton(hwndDlg, IDC_CHK_DESTTCP, add_edit_addr.port != -1);
+ if(add_edit_addr.port != -1) {
+ hw = GetDlgItem(hwndDlg, IDC_ED_DESTPORT);
+ EnableWindow(hw, TRUE);
+ SetDlgItemInt(hwndDlg, IDC_ED_DESTPORT, add_edit_addr.port, FALSE);
+ }
+ {
+ int num_protocols;
+ PROTOACCOUNT **pppDesc;
+
+ ProtoEnumAccounts(&num_protocols,&pppDesc);
+ hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTPROTO);
+ SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)Translate("<none>"));
+ SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)Translate("<all>"));
+ for(int i = 0; i < num_protocols; i++) {
+ SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)pppDesc[i]->tszAccountName);
+ }
+
+ if(add_edit_addr.pszProto[0] == '\0') {
+ SendMessage(hw, CB_SETCURSEL, 0, 0);
+ } else {
+ SendMessage(hw, CB_SELECTSTRING, 0, (LPARAM)add_edit_addr.pszProto);
+ hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTSTAT);
+ EnableWindow(hw, TRUE);
+ SendMessage(hw, CB_SETCURSEL, (WPARAM)(add_edit_addr.set_status - ID_STATUS_OFFLINE), 0);
+ hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTSTAT2);
+ EnableWindow(hw, TRUE);
+ SendMessage(hw, CB_SETCURSEL, (WPARAM)(add_edit_addr.get_status - ID_STATUS_OFFLINE), 0);
+ }
+ }
+ // ? doesn't work? ?
+ hw = GetDlgItem(hwndDlg, IDC_ED_DESTLAB);
+ SetFocus(hw);
+ }
+ return FALSE;
+ case WM_COMMAND:
+ if (HIWORD( wParam ) == LBN_SELCHANGE && LOWORD(wParam) == IDC_COMBO_DESTPROTO) {
+ hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTPROTO);
+ sel = SendMessage(hw, CB_GETCURSEL, 0, 0);
+ if(sel != CB_ERR) {
+ hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTSTAT);
+ EnableWindow(hw, sel != 0);
+ hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTSTAT2);
+ EnableWindow(hw, sel != 0);
+ }
+ }
+
+ if ( HIWORD( wParam ) == BN_CLICKED ) {
+ switch( LOWORD( wParam )) {
+ case IDC_CHK_DESTTCP:
+ hw = GetDlgItem(hwndDlg, IDC_ED_DESTPORT);
+ EnableWindow(hw, IsDlgButtonChecked(hwndDlg, IDC_CHK_DESTTCP));
+ break;
+ case IDOK:
+ GetDlgItemText(hwndDlg, IDC_ED_DESTADDR, add_edit_addr.pszName, MAX_PINGADDRESS_STRING_LENGTH);
+ GetDlgItemText(hwndDlg, IDC_ED_DESTLAB, add_edit_addr.pszLabel, MAX_PINGADDRESS_STRING_LENGTH);
+ GetDlgItemText(hwndDlg, IDC_ED_COMMAND, add_edit_addr.pszCommand, MAX_PATH);
+ GetDlgItemText(hwndDlg, IDC_ED_PARAMS, add_edit_addr.pszParams, MAX_PATH);
+
+ hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTPROTO);
+ if(SendMessage(hw, CB_GETCURSEL, 0, 0) != -1) {
+ GetDlgItemText(hwndDlg, IDC_COMBO_DESTPROTO, add_edit_addr.pszProto, MAX_PINGADDRESS_STRING_LENGTH);
+ if(!strcmp(add_edit_addr.pszProto, Translate("<none>"))) add_edit_addr.pszProto[0] = '\0';
+ else {
+ hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTSTAT);
+ sel = SendMessage(hw, CB_GETCURSEL, 0, 0);
+ if(sel != -1)
+ add_edit_addr.set_status = ID_STATUS_OFFLINE + sel;
+ hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTSTAT2);
+ sel = SendMessage(hw, CB_GETCURSEL, 0, 0);
+ if(sel != -1)
+ add_edit_addr.get_status = ID_STATUS_OFFLINE + sel;
+ }
+ } else
+ add_edit_addr.pszProto[0] = '\0';
+
+ if(IsDlgButtonChecked(hwndDlg, IDC_CHK_DESTTCP)) {
+ BOOL tr;
+ int port = GetDlgItemInt(hwndDlg, IDC_ED_DESTPORT, &tr, FALSE);
+ if(tr) add_edit_addr.port = port;
+ else add_edit_addr.port = -1;
+ } else
+ add_edit_addr.port = -1;
+
+ EndDialog(hwndDlg, IDOK);
+ break;
+ case IDCANCEL:
+ EndDialog(hwndDlg, IDCANCEL);
+ break;
+ }
+
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL Edit(HWND hwnd, PINGADDRESS &addr) {
+ add_edit_addr = addr;
+ if(DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG3), hwnd, DlgProcDestEdit) == IDOK) {
+ addr = add_edit_addr;
+ return TRUE;
+ }
+ return FALSE;
+}
+// ping hosts list window
+static INT_PTR CALLBACK DlgProcOpts2(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ //OPENFILENAME ofn = {0};
+ HWND hw;
+ int sel;
+
+ switch ( msg ) {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault( hwndDlg );
+
+ Lock(&data_list_cs, "init options dialog");
+ temp_list = data_list;
+ Unlock(&data_list_cs);
+
+ hw = GetDlgItem(hwndDlg, IDC_LST_DEST);
+ for(PINGLIST::Iterator i = temp_list.start(); i.has_val(); i.next()) {
+ int index = SendMessage(hw, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)i.val().pszLabel);
+ SendMessage(hw, LB_SETITEMDATA, index, (LPARAM)&i.val());
+ }
+
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ if (HIWORD( wParam ) == LBN_SELCHANGE && LOWORD(wParam) == IDC_LST_DEST) {
+ hw = GetDlgItem(hwndDlg, IDC_LST_DEST);
+ sel = SendMessage(hw, LB_GETCURSEL, 0, 0);
+ if(sel != LB_ERR) {
+ hw = GetDlgItem(hwndDlg, IDC_BTN_DESTREM);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_BTN_DESTEDIT);
+ EnableWindow(hw, TRUE);
+
+ hw = GetDlgItem(hwndDlg, IDC_BTN_DESTUP);
+ EnableWindow(hw, (sel > 0));
+ hw = GetDlgItem(hwndDlg, IDC_LST_DEST);
+ int count = SendMessage(hw, LB_GETCOUNT, 0, 0);
+ hw = GetDlgItem(hwndDlg, IDC_BTN_DESTDOWN);
+ EnableWindow(hw, (sel < count - 1));
+ }
+ }
+
+ if ( HIWORD( wParam ) == BN_CLICKED ) {
+ switch( LOWORD( wParam )) {
+ case IDC_BTN_DESTEDIT:
+ hw = GetDlgItem(hwndDlg, IDC_LST_DEST);
+ sel = SendMessage(hw, LB_GETCURSEL, 0, 0);
+ if(sel != LB_ERR) {
+ PINGADDRESS *item = (PINGADDRESS *)SendMessage(hw, LB_GETITEMDATA, sel, 0);
+ PINGADDRESS temp = *item;
+ if(Edit(hwndDlg, temp)) {
+ *item = temp;
+ SendMessage(hw, LB_DELETESTRING, (WPARAM)sel, (LPARAM)0);
+ SendMessage(hw, LB_INSERTSTRING, (WPARAM)sel, (LPARAM)item->pszLabel);
+ SendMessage(hw, LB_SETITEMDATA, (WPARAM)sel, (LPARAM)item);
+ SendMessage(hw, LB_SETCURSEL, (WPARAM)sel, 0);
+
+ hw = GetDlgItem(hwndDlg, IDC_BTN_DESTREM);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_BTN_DESTEDIT);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_BTN_DESTUP);
+ EnableWindow(hw, sel > 0);
+ hw = GetDlgItem(hwndDlg, IDC_BTN_DESTDOWN);
+ int count = SendMessage(hw, LB_GETCOUNT, 0, 0);
+ EnableWindow(hw, (sel < count - 1));
+
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+ }
+ break;
+ case IDC_BTN_DESTADD:
+
+ memset(&add_edit_addr,0,sizeof(add_edit_addr));
+ add_edit_addr.cbSize = sizeof(add_edit_addr);
+ add_edit_addr.port = -1;
+ add_edit_addr.set_status = ID_STATUS_ONLINE;
+ add_edit_addr.get_status = ID_STATUS_OFFLINE;
+ add_edit_addr.status = PS_NOTRESPONDING;
+ add_edit_addr.item_id = 0;
+
+ if(DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG3), hwndDlg, DlgProcDestEdit) == IDOK) {
+
+ temp_list.add(add_edit_addr);
+
+ hw = GetDlgItem(hwndDlg, IDC_LST_DEST);
+ int index = SendMessage(hw, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)add_edit_addr.pszLabel);
+ hw = GetDlgItem(hwndDlg, IDC_LST_DEST);
+ SendMessage(hw, LB_SETCURSEL, (WPARAM)index, 0);
+
+ hw = GetDlgItem(hwndDlg, IDC_BTN_DESTREM);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_BTN_DESTEDIT);
+ EnableWindow(hw, TRUE);
+
+ sel = temp_list.size() - 1;
+ hw = GetDlgItem(hwndDlg, IDC_BTN_DESTUP);
+ EnableWindow(hw, (sel > 0));
+ hw = GetDlgItem(hwndDlg, IDC_LST_DEST);
+ int count = SendMessage(hw, LB_GETCOUNT, 0, 0);
+ hw = GetDlgItem(hwndDlg, IDC_BTN_DESTDOWN);
+ EnableWindow(hw, (sel < count - 1));
+
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+
+ break;
+ case IDC_BTN_DESTREM:
+ hw = GetDlgItem(hwndDlg, IDC_LST_DEST);
+ sel = SendMessage(hw, LB_GETCURSEL, 0, 0);
+ if(sel != LB_ERR) {
+ PINGADDRESS *item = (PINGADDRESS *)SendMessage(hw, LB_GETITEMDATA, sel, 0);
+ SendMessage(hw, LB_DELETESTRING, (WPARAM)sel, 0);
+ temp_list.remove(*item);
+ }
+
+ hw = GetDlgItem(hwndDlg, IDC_BTN_DESTREM);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_BTN_DESTEDIT);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_BTN_DESTUP);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_BTN_DESTDOWN);
+ EnableWindow(hw, FALSE);
+
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_BTN_DESTDOWN:
+ {
+ hw = GetDlgItem(hwndDlg, IDC_LST_DEST);
+ int sel2 = SendMessage(hw, LB_GETCURSEL, 0, 0);
+ if(sel2 != LB_ERR) {
+ PINGADDRESS *item = (PINGADDRESS *)SendMessage(hw, LB_GETITEMDATA, sel2, 0),
+ *item2 = (PINGADDRESS *)SendMessage(hw, LB_GETITEMDATA, sel2 + 1, 0);
+ add_edit_addr = *item;
+ *item = *item2;
+ *item2 = add_edit_addr;
+
+ // keep indexes the same, as they're used for sorting the binary tree
+ int index = item->index, index2 = item2->index;
+ item->index = index2;
+ item2->index = index;
+
+ SendMessage(hw, LB_DELETESTRING, (WPARAM)sel2, (LPARAM)0);
+ SendMessage(hw, LB_INSERTSTRING, (WPARAM)sel2, (LPARAM)item->pszLabel);
+ SendMessage(hw, LB_SETITEMDATA, (WPARAM)sel2, (LPARAM)item);
+ SendMessage(hw, LB_DELETESTRING, (WPARAM)(sel2 + 1), (LPARAM)0);
+ SendMessage(hw, LB_INSERTSTRING, (WPARAM)(sel2 + 1), (LPARAM)item2->pszLabel);
+ SendMessage(hw, LB_SETITEMDATA, (WPARAM)(sel2 + 1), (LPARAM)item2);
+ SendMessage(hw, LB_SETCURSEL, (WPARAM)(sel2 + 1), 0);
+
+ hw = GetDlgItem(hwndDlg, IDC_BTN_DESTUP);
+ EnableWindow(hw, (sel2 + 1 > 0));
+ hw = GetDlgItem(hwndDlg, IDC_LST_DEST);
+ int count = SendMessage(hw, LB_GETCOUNT, 0, 0);
+ hw = GetDlgItem(hwndDlg, IDC_BTN_DESTDOWN);
+ EnableWindow(hw, (sel2 + 1 < count - 1));
+
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+ }
+ break;
+ case IDC_BTN_DESTUP:
+ {
+ hw = GetDlgItem(hwndDlg, IDC_LST_DEST);
+ int sel2 = SendMessage(hw, LB_GETCURSEL, 0, 0);
+ if(sel2 != LB_ERR) {
+ PINGADDRESS *item = (PINGADDRESS *)SendMessage(hw, LB_GETITEMDATA, sel2, 0),
+ *item2 = (PINGADDRESS *)SendMessage(hw, LB_GETITEMDATA, sel2 - 1, 0);
+ add_edit_addr = *item;
+ *item = *item2;
+ *item2 = add_edit_addr;
+
+ // keep indexes the same, as they're used for sorting the binary tree
+ int index = item->index, index2 = item2->index;
+ item->index = index2;
+ item2->index = index;
+
+ SendMessage(hw, LB_DELETESTRING, (WPARAM)sel2, (LPARAM)0);
+ SendMessage(hw, LB_INSERTSTRING, (WPARAM)sel2, (LPARAM)item->pszLabel);
+ SendMessage(hw, LB_SETITEMDATA, (WPARAM)sel2, (LPARAM)item);
+
+ SendMessage(hw, LB_DELETESTRING, (WPARAM)(sel2 - 1), (LPARAM)0);
+ SendMessage(hw, LB_INSERTSTRING, (WPARAM)(sel2 - 1), (LPARAM)item2->pszLabel);
+ SendMessage(hw, LB_SETITEMDATA, (WPARAM)(sel2 - 1), (LPARAM)item2);
+
+ SendMessage(hw, LB_SETCURSEL, (WPARAM)(sel2 - 1), 0);
+
+ hw = GetDlgItem(hwndDlg, IDC_BTN_DESTUP);
+ EnableWindow(hw, (sel2 - 1 > 0));
+ hw = GetDlgItem(hwndDlg, IDC_LST_DEST);
+ int count = SendMessage(hw, LB_GETCOUNT, 0, 0);
+ hw = GetDlgItem(hwndDlg, IDC_BTN_DESTDOWN);
+ EnableWindow(hw, (sel2 - 1 < count - 1));
+
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+ }
+
+ break;
+ }
+ }
+ if(LOWORD(wParam) == IDC_BGCOL
+ || LOWORD(wParam) == IDC_SP_INDENT || LOWORD(wParam) == IDC_SP_ROWHEIGHT)
+ {
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+ break;
+
+ case WM_NOTIFY:
+ if (((LPNMHDR)lParam)->code == PSN_APPLY ) {
+ CallService(PLUG "/SetAndSavePingList", (WPARAM)&temp_list, 0);
+ CallService(PLUG "/GetPingList", 0, (LPARAM)&temp_list);
+ // the following will be affected due to list rebuild event
+ //if(hWakeEvent) SetEvent(hWakeEvent);
+ return TRUE;
+ }
+ break;
+
+ }
+ return FALSE;
+}
+
+int PingOptInit(WPARAM wParam,LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = { 0 };
+ odp.cbSize = sizeof(odp);
+ odp.hInstance = hInst;
+ odp.flags = ODPF_BOLDGROUPS|ODPF_TCHAR;
+ odp.ptszGroup = LPGENT("Network");
+ odp.ptszTitle = LPGENT("PING");
+
+ odp.ptszTab = LPGENT("Settings");
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_DIALOG1);
+ odp.pfnDlgProc = DlgProcOpts;
+ Options_AddPage(wParam,&odp);
+
+ odp.ptszTab = LPGENT("Hosts");
+ odp.pszTemplate = MAKEINTRESOURCE(IDD_DIALOG2);
+ odp.pfnDlgProc = DlgProcOpts2;
+ Options_AddPage(wParam,&odp);
+
+ return 0;
+}
+
+void LoadOptions() {
+ options.ping_period = DBGetContactSettingDword(NULL, PLUG, "PingPeriod", DEFAULT_PING_PERIOD);
+
+ options.ping_timeout = DBGetContactSettingDword(NULL, PLUG, "PingTimeout", DEFAULT_PING_TIMEOUT);
+ CallService(PLUG "/SetPingTimeout", (WPARAM)options.ping_timeout, 0);
+ options.show_popup = (DBGetContactSettingByte(NULL, PLUG, "ShowPopup", DEFAULT_SHOW_POPUP ? 1 : 0) == 1);
+ options.show_popup2 = (DBGetContactSettingByte(NULL, PLUG, "ShowPopup2", DEFAULT_SHOW_POPUP2 ? 1 : 0) == 1);
+ options.block_reps = (DBGetContactSettingByte(NULL, PLUG, "BlockReps", DEFAULT_BLOCK_REPS ? 1 : 0) == 1);
+ options.logging = (DBGetContactSettingByte(NULL, PLUG, "LoggingEnabled", DEFAULT_LOGGING_ENABLED ? 1 : 0) == 1);
+
+ options.no_test_icon = (DBGetContactSettingByte(NULL, PLUG, "NoTestStatus", DEFAULT_NO_TEST_ICON ? 1 : 0) == 1);
+
+ options.indent = DBGetContactSettingWord(NULL, PLUG, "Indent", 0);
+ options.row_height = DBGetContactSettingWord(NULL, PLUG, "RowHeight", GetSystemMetrics(SM_CYSMICON));
+
+ options.retries = DBGetContactSettingDword(NULL, PLUG, "Retries", 0);
+
+ CallService(PLUG "/GetLogFilename", (WPARAM)MAX_PATH, (LPARAM)options.log_filename);
+
+ ICMP::get_instance()->set_timeout(options.ping_timeout * 1000);
+
+ options.attach_to_clist = (DBGetContactSettingByte(NULL, PLUG, "AttachToClist", DEFAULT_ATTACH_TO_CLIST ? 1 : 0) == 1);
+ options.log_csv = (DBGetContactSettingByte(NULL, PLUG, "LogCSV", 0) == 1);
+}
+
+void SaveOptions() {
+ DBWriteContactSettingDword(NULL, PLUG, "PingPeriod", options.ping_period);
+ DBWriteContactSettingDword(NULL, PLUG, "PingTimeout", options.ping_timeout);
+ CallService(PLUG "/SetPingTimeout", (WPARAM)options.ping_timeout, 0);
+ DBWriteContactSettingByte(NULL, PLUG, "ShowPopup", options.show_popup ? 1 : 0);
+ DBWriteContactSettingByte(NULL, PLUG, "ShowPopup2", options.show_popup2 ? 1 : 0);
+ DBWriteContactSettingByte(NULL, PLUG, "BlockReps", options.block_reps ? 1 : 0);
+ DBWriteContactSettingByte(NULL, PLUG, "LoggingEnabled", options.logging ? 1 : 0);
+
+ DBWriteContactSettingByte(NULL, PLUG, "NoTestStatus", options.no_test_icon ? 1 : 0);
+
+ DBWriteContactSettingWord(NULL, PLUG, "Indent", options.indent);
+ DBWriteContactSettingWord(NULL, PLUG, "RowHeight", options.row_height);
+
+ DBWriteContactSettingDword(NULL, PLUG, "Retries", (DWORD)options.retries);
+
+ CallService(PLUG "/SetLogFilename", (WPARAM)MAX_PATH, (LPARAM)options.log_filename);
+
+ ICMP::get_instance()->set_timeout(options.ping_timeout * 1000);
+
+ DBWriteContactSettingByte(NULL, PLUG, "AttachToClist", options.attach_to_clist ? 1 : 0);
+ DBWriteContactSettingByte(NULL, PLUG, "LogCSV", options.log_csv ? 1 : 0);
+}
diff --git a/plugins/Ping/options.h b/plugins/Ping/options.h
new file mode 100644
index 0000000000..1963649bfb
--- /dev/null
+++ b/plugins/Ping/options.h
@@ -0,0 +1,26 @@
+#ifndef _PING_OPTIONS
+#define _PING_OPTIONS
+
+#include "pinglist.h"
+#include "utils.h"
+#include "icmp.h"
+#include "pingthread.h"
+
+#include "resource.h"
+
+// wake event for ping thread
+extern HANDLE hWakeEvent;
+
+extern PingOptions options;
+extern PINGADDRESS add_edit_addr;
+
+INT_PTR CALLBACK DlgProcDestEdit(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+int PingOptInit(WPARAM wParam,LPARAM lParam);
+
+BOOL Edit(HWND hwnd, PINGADDRESS &addr);
+
+void LoadOptions();
+void SaveOptions();
+
+#endif
diff --git a/plugins/Ping/ping.cpp b/plugins/Ping/ping.cpp
new file mode 100644
index 0000000000..10803ce5c5
--- /dev/null
+++ b/plugins/Ping/ping.cpp
@@ -0,0 +1,179 @@
+#include "common.h"
+#include "ping.h"
+#include <list>
+HINSTANCE hInst;
+int hLangpack = 0;
+
+HANDLE hNetlibUser = 0;
+HANDLE hFillListEvent = 0;
+
+bool use_raw_ping = true;
+
+// plugin stuff
+PLUGININFOEX pluginInfo={
+ sizeof(PLUGININFOEX),
+ "Ping Plugin",
+ PLUGIN_MAKE_VERSION(0, 9, 1, 1),
+ "Ping labelled IP addresses or domain names.",
+ "Scott Ellis",
+ "mail@scottellis.com.au",
+ "© 2005 Scott Ellis",
+ "http://www.scottellis.com.au/",
+ UNICODE_AWARE, //not transient
+ { 0x760ea901, 0xc0c2, 0x446c, { 0x80, 0x29, 0x94, 0xc3, 0xbc, 0x47, 0xc4, 0x5e } } // {760EA901-C0C2-446c-8029-94C3BC47C45E}
+};
+
+extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ hInst=hinstDLL;
+ DisableThreadLibraryCalls(hInst);
+ return TRUE;
+}
+
+extern "C" PING_API PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+static const MUUID interfaces[] = {MIID_PING, MIID_LAST};
+extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+
+
+void CreatePluginServices() {
+ // general
+ CreateServiceFunction(PLUG "/Ping", PluginPing);
+ CreateServiceFunction(PLUG "/DblClick", DblClick);
+
+ // list
+ CreateServiceFunction(PLUG "/ClearPingList", ClearPingList);
+ CreateServiceFunction(PLUG "/GetPingList", GetPingList);
+ CreateServiceFunction(PLUG "/SetPingList", SetPingList);
+ CreateServiceFunction(PLUG "/SetAndSavePingList", SetAndSavePingList);
+ CreateServiceFunction(PLUG "/LoadPingList", LoadPingList);
+ CreateServiceFunction(PLUG "/SavePingList", SavePingList);
+
+ reload_event_handle = CreateHookableEvent(PLUG "/ListReload");
+
+ //log
+ CreateServiceFunction(PLUG "/Log", Log);
+ CreateServiceFunction(PLUG "/ViewLogData", ViewLogData);
+ CreateServiceFunction(PLUG "/GetLogFilename", GetLogFilename);
+ CreateServiceFunction(PLUG "/SetLogFilename", SetLogFilename);
+
+ // menu
+ CreateServiceFunction(PLUG "/DisableAll", PingDisableAll);
+ CreateServiceFunction(PLUG "/EnableAll", PingEnableAll);
+ CreateServiceFunction(PLUG "/ToggleEnabled", ToggleEnabled);
+ CreateServiceFunction(PLUG "/ShowGraph", ShowGraph);
+ CreateServiceFunction(PLUG "/Edit", EditContact);
+
+}
+
+int OnShutdown(WPARAM wParam, LPARAM lParam) {
+ graphs_cleanup();
+
+ UnhookEvent(hFillListEvent);
+
+ if(use_raw_ping)
+ cleanup_raw_ping();
+ else
+ ICMP::cleanup();
+
+ DeinitList();
+
+ return 0;
+}
+
+int OnModulesLoaded(WPARAM wParam, LPARAM lParam) {
+ NETLIBUSER nl_user = {0};
+ nl_user.cbSize = sizeof(nl_user);
+ nl_user.szSettingsModule = PLUG;
+ //nl_user.flags = NUF_OUTGOING | NUF_HTTPGATEWAY | NUF_NOOPTIONS;
+ //nl_user.flags = NUF_OUTGOING | NUF_NOOPTIONS;
+ nl_user.flags = NUF_OUTGOING | NUF_HTTPCONNS | NUF_TCHAR;
+ nl_user.ptszDescriptiveName = LPGENT("Ping Plugin");
+ nl_user.szHttpGatewayHello = 0;
+ nl_user.szHttpGatewayUserAgent = 0;
+ nl_user.pfnHttpGatewayInit = 0;
+ nl_user.pfnHttpGatewayWrapSend = 0;
+ nl_user.pfnHttpGatewayUnwrapRecv = 0;
+
+ hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nl_user);
+
+ InitUtils();
+
+ InitMenus();
+
+ hFillListEvent = HookEvent(PLUG "/ListReload", FillList);
+
+ if(!DBGetContactSettingByte(0, PLUG, "PingPlugImport", 0)) {
+ if(DBGetContactSettingDword(0, "PingPlug", "NumEntries", 0)) {
+ import_ping_addresses();
+ DBWriteContactSettingByte(0, PLUG, "PingPlugImport", 1);
+ }
+ }
+
+ InitList();
+
+ CallService(PLUG "/LoadPingList", 0, 0);
+
+ graphs_init();
+
+ if(options.logging) CallService(PLUG "/Log", (WPARAM)"start", 0);
+
+ return 0;
+}
+
+extern "C" PING_API int Load(void)
+{
+ //if(init_raw_ping()) {
+ //MessageBox(0, Translate("Failed to initialize. Plugin disabled."), Translate("Ping Plugin"), MB_OK | MB_ICONERROR);
+ //return 1;
+ use_raw_ping = false;
+ //}
+ DBWriteContactSettingByte(0, PLUG, "UsingRawSockets", (BYTE)use_raw_ping);
+
+ DuplicateHandle( GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &mainThread, THREAD_SET_CONTEXT, FALSE, 0 );
+ hWakeEvent = CreateEvent(NULL, FALSE, FALSE, _T("Local\\ThreadWaitEvent"));
+
+ InitializeCriticalSection(&list_cs);
+ InitializeCriticalSection(&thread_finished_cs);
+ InitializeCriticalSection(&list_changed_cs);
+ InitializeCriticalSection(&data_list_cs);
+
+ // create services before loading options - so we can have the 'getlogfilename' service!
+ CreatePluginServices();
+
+ LoadOptions();
+
+ SkinAddNewSound("PingTimeout", "Ping Timout", 0);
+ SkinAddNewSound("PingReply", "Ping Reply", 0);
+
+ HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded);
+
+ HookEvent(ME_OPT_INITIALISE, PingOptInit );
+
+ HookEvent(ME_SYSTEM_PRESHUTDOWN, OnShutdown);
+
+ return 0;
+}
+
+extern "C" PING_API int Unload(void)
+{
+ SavePingList(0, 0);
+
+ DeleteCriticalSection(&list_cs);
+ DeleteCriticalSection(&thread_finished_cs);
+ DeleteCriticalSection(&list_changed_cs);
+ DeleteCriticalSection(&data_list_cs);
+
+ CloseHandle( mainThread );
+
+ if(options.logging) CallService(PLUG "/Log", (WPARAM)"stop", 0);
+
+ return 0;
+}
diff --git a/plugins/Ping/ping.h b/plugins/Ping/ping.h
new file mode 100644
index 0000000000..8a1b1730bd
--- /dev/null
+++ b/plugins/Ping/ping.h
@@ -0,0 +1,41 @@
+/*
+Based on the
+Miranda plugin template, originally by Richard Hughes
+http://miranda-icq.sourceforge.net/
+
+© 2004 Scott Ellis
+
+*/
+
+#ifndef _PING
+#define _PING
+
+
+// The following ifdef block is the standard way of creating macros which make exporting
+// from a DLL simpler. All files within this DLL are compiled with the PINGPROTO_EXPORTS
+// symbol defined on the command line. this symbol should not be defined on any project
+// that uses this DLL. This way any other project whose source files include this file see
+// PINGPROTO_API functions as being imported from a DLL, wheras this DLL sees symbols
+// defined with this macro as being exported.
+#ifdef PING_EXPORTS
+#define PING_API __declspec(dllexport)
+#else
+#define PING_API __declspec(dllimport)
+#endif
+
+#include "utils.h"
+#include "options.h"
+#include "pinglist.h"
+#include "log.h"
+#include "pingthread.h"
+#include "menu.h"
+#include "rawping.h"
+
+// globals
+extern PLUGININFOEX pluginInfo;
+
+extern "C" PING_API PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion);
+extern "C" PING_API int Load(void);
+extern "C" PING_API int Unload(void);
+
+#endif
diff --git a/plugins/Ping/ping.rc b/plugins/Ping/ping.rc
new file mode 100644
index 0000000000..b7e6b7d3c6
--- /dev/null
+++ b/plugins/Ping/ping.rc
@@ -0,0 +1,227 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (Australia) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON_DISABLED ICON "grey.ico"
+IDI_ICON_NOTRESPONDING ICON "red.ico"
+IDI_ICON_RESPONDING ICON "green.ico"
+IDI_ICON_TESTING ICON "yellow.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DIALOG1 DIALOGEX 0, 0, 303, 227
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ RTEXT "Delay between pings (secs):",IDC_STATIC,9,21,121,8
+ EDITTEXT IDC_PPM,135,18,40,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
+ CONTROL "Timeout",IDC_CHECKPOPUP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,20,72,10
+ RTEXT "Ping timeout (secs):",IDC_STATIC,9,41,121,8
+ EDITTEXT IDC_PT,135,39,40,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
+ GROUPBOX "Logging",IDC_STATIC,4,165,293,55
+ CONTROL "Log to File",IDC_CHK_LOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,39,178,69,10
+ LTEXT "Log Filename:",IDC_STATIC,14,198,56,8
+ EDITTEXT IDC_ED_FILENAME,74,195,158,14,ES_AUTOHSCROLL
+ GROUPBOX "Network",IDC_STATIC,4,5,205,72
+ GROUPBOX "PopUps",IDC_STATIC,218,5,79,72
+ CONTROL "Reply",IDC_CHECKPOPUP2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,36,72,10
+ CONTROL "Block Repetitions",IDC_CHK_BLOCK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,60,72,10
+ PUSHBUTTON "View Log",IDC_BTN_VIEWLOG,238,176,54,14
+ PUSHBUTTON "Browse...",IDC_BTN_LOGBROWSE,238,194,54,16
+ GROUPBOX "Interface",IDC_STATIC,4,84,293,76
+ CONTROL "Do not change icon when testing",IDC_CHK_NOTESTICON,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,145,181,10
+ LTEXT "Use the Customize/Fonts options to change text size and colour.",IDC_STATFS,20,101,174,18
+ RTEXT "Indent:",IDC_STATIC,44,127,33,8
+ EDITTEXT IDC_EDIT1,89,124,33,15,ES_AUTOHSCROLL
+ CONTROL "Spin2",IDC_SP_INDENT,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,121,124,12,15
+ RTEXT "Row height:",IDC_STATIC,154,127,52,8
+ EDITTEXT IDC_EDIT2,217,124,33,15,ES_AUTOHSCROLL
+ CONTROL "Spin3",IDC_SP_ROWHEIGHT,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,250,124,12,15
+ RTEXT "Repeats for success/failure:",IDC_STATIC,9,60,121,8
+ EDITTEXT IDC_RPT,135,59,40,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT
+ CONTROL "Attach to contact list",IDC_CHK_ATTACH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,201,145,94,10
+ CONTROL "Use CSV format",IDC_CHK_LOGCSV,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,136,178,96,10
+END
+
+IDD_DIALOG2 DIALOGEX 0, 0, 285, 212
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ PUSHBUTTON "Add",IDC_BTN_DESTADD,30,172,38,15
+ LISTBOX IDC_LST_DEST,29,32,228,128,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Remove",IDC_BTN_DESTREM,124,172,38,15,WS_DISABLED
+ PUSHBUTTON "Edit",IDC_BTN_DESTEDIT,77,172,38,15,WS_DISABLED
+ PUSHBUTTON "Up",IDC_BTN_DESTUP,171,172,38,15,WS_DISABLED
+ PUSHBUTTON "Down",IDC_BTN_DESTDOWN,218,172,38,15,WS_DISABLED
+END
+
+IDD_DIALOG3 DIALOGEX 0, 0, 263, 291
+STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Edit Host"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,78,270,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,134,270,50,14
+ LTEXT "Address:",IDC_STATIC,24,34,37,8
+ LTEXT "Label:",IDC_STATIC,31,49,30,8
+ EDITTEXT IDC_ED_DESTADDR,67,30,154,12,ES_AUTOHSCROLL | ES_WANTRETURN
+ EDITTEXT IDC_ED_DESTLAB,67,48,154,12,ES_AUTOHSCROLL | ES_WANTRETURN
+ CONTROL "TCP Connect",IDC_CHK_DESTTCP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,72,69,71,10
+ LTEXT "Port:",IDC_STATIC,151,69,25,8
+ EDITTEXT IDC_ED_DESTPORT,181,66,40,12,ES_RIGHT | ES_AUTOHSCROLL | ES_WANTRETURN | ES_NUMBER | WS_DISABLED
+ CTEXT "Control Protocol:",IDC_STATIC,84,106,92,8
+ COMBOBOX IDC_COMBO_DESTPROTO,83,119,97,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_COMBO_DESTSTAT,156,158,76,30,CBS_DROPDOWNLIST | WS_DISABLED | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Set my status to:",IDC_STATIC,151,143,87,8
+ LTEXT "On success, if my status is:",IDC_STATIC,25,143,115,8
+ COMBOBOX IDC_COMBO_DESTSTAT2,33,158,90,30,CBS_DROPDOWNLIST | WS_DISABLED | WS_VSCROLL | WS_TABSTOP
+ EDITTEXT IDC_ED_COMMAND,34,197,195,14,ES_AUTOHSCROLL
+ CTEXT "Execute the following command on double-click:",IDC_STATIC,28,182,207,8
+ GROUPBOX "Contact",IDC_STATIC,7,7,249,86
+ GROUPBOX "Protocols",IDC_STATIC,7,97,249,166
+ EDITTEXT IDC_ED_PARAMS,33,236,195,14,ES_AUTOHSCROLL
+ CTEXT "(Optional) Command Parameters:",IDC_STATIC,27,219,207,8
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_DIALOG1, DIALOG
+ BEGIN
+ LEFTMARGIN, 4
+ RIGHTMARGIN, 297
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 220
+ END
+
+ IDD_DIALOG2, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 278
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 205
+ END
+
+ IDD_DIALOG3, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 256
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 284
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_MENU1 MENU
+BEGIN
+ POPUP "Menu"
+ BEGIN
+ MENUITEM "Graph", ID_MENU_GRAPH
+ MENUITEM "Enable", ID_MENU_TOGGLE
+ MENUITEM "Edit", ID_MENU_EDIT
+ MENUITEM SEPARATOR
+ MENUITEM "Disable all pings", ID_MENU_DISABLEALLPINGS
+ MENUITEM "Enable all pings", ID_MENU_ENABLEALLPINGS
+ MENUITEM SEPARATOR
+ MENUITEM "Options...", ID_MENU_OPTIONS
+ MENUITEM "Hosts...", ID_MENU_DESTINATIONS
+ END
+END
+
+#endif // English (Australia) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/Ping/ping.vcxproj b/plugins/Ping/ping.vcxproj
new file mode 100644
index 0000000000..9d3b0a879e
--- /dev/null
+++ b/plugins/Ping/ping.vcxproj
@@ -0,0 +1,393 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>ping</ProjectName>
+ <ProjectGuid>{F31BD1B6-EE9D-4F76-A047-F8AEADC26086}</ProjectGuid>
+ <RootNamespace>ping</RootNamespace>
+ <Keyword>MFCProj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>Dynamic</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>Dynamic</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>Dynamic</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>Dynamic</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</IgnoreImportLibrary>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\Obj\$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</GenerateManifest>
+ <EmbedManifest Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</EmbedManifest>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</IgnoreImportLibrary>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Plugins\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</GenerateManifest>
+ <EmbedManifest Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</EmbedManifest>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</IgnoreImportLibrary>
+ <IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</IgnoreImportLibrary>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Debug/ping.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;PING_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>common.h</PrecompiledHeaderFile>
+ <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
+ <ObjectFileName>.\Debug/</ObjectFileName>
+ <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0c09</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>user32.lib;gdi32.lib;ws2_32.lib;shell32.lib;comdlg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>.\Debug/pingplug.pdb</ProgramDatabaseFile>
+ <BaseAddress>0x22040000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin10\lib</AdditionalLibraryDirectories>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Debug/ping.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Release/ping.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <AdditionalIncludeDirectories>../../include;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;PING_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>common.h</PrecompiledHeaderFile>
+ <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
+ <ObjectFileName>.\Release/</ObjectFileName>
+ <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0c09</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wsock32.lib;user32.lib;gdi32.lib;shell32.lib;comdlg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>.\Release/pingplug.pdb</ProgramDatabaseFile>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <BaseAddress>0x22040000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin10\lib</AdditionalLibraryDirectories>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Release/ping.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>.\Debug/ping.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;PING_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>common.h</PrecompiledHeaderFile>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0c09</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>user32.lib;gdi32.lib;ws2_32.lib;shell32.lib;comdlg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>.\Debug/pingplug.pdb</ProgramDatabaseFile>
+ <BaseAddress>0x22040000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin10\lib</AdditionalLibraryDirectories>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Debug/ping.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>X64</TargetEnvironment>
+ <TypeLibraryName>.\Release/ping.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <OmitFramePointers>true</OmitFramePointers>
+ <AdditionalIncludeDirectories>../../include;../../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;PING_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>false</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>common.h</PrecompiledHeaderFile>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0c09</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;wsock32.lib;user32.lib;gdi32.lib;shell32.lib;comdlg32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>.\Release/pingplug.pdb</ProgramDatabaseFile>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <BaseAddress>0x22040000</BaseAddress>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX64</TargetMachine>
+ <AdditionalLibraryDirectories>$(ProfileDir)..\..\bin10\lib</AdditionalLibraryDirectories>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Release/ping.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="icmp.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="log.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="menu.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="options.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="ping.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="pinggraph.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="pinglist.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="pingthread.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="rawping.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="utils.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="collection.h" />
+ <ClInclude Include="common.h" />
+ <ClInclude Include="icmp.h" />
+ <ClInclude Include="log.h" />
+ <ClInclude Include="menu.h" />
+ <ClInclude Include="options.h" />
+ <ClInclude Include="ping.h" />
+ <ClInclude Include="pinggraph.h" />
+ <ClInclude Include="pinglist.h" />
+ <ClInclude Include="pingthread.h" />
+ <ClInclude Include="rawping.h" />
+ <ClInclude Include="resource.h" />
+ <ClInclude Include="utils.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="green.ico" />
+ <None Include="grey.ico" />
+ <None Include="ico00001.ico" />
+ <None Include="icon1.ico" />
+ <None Include="icon2.ico" />
+ <None Include="icon3.ico" />
+ <None Include="red.ico" />
+ <None Include="yellow.ico" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="ping.rc">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/Ping/ping.vcxproj.filters b/plugins/Ping/ping.vcxproj.filters
new file mode 100644
index 0000000000..1e53e1ccad
--- /dev/null
+++ b/plugins/Ping/ping.vcxproj.filters
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{ee28df87-65f4-4762-acba-155d7607d5ab}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{c454feba-dfe0-4f93-ba62-c6b5b8fc96b7}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{392f6369-40fa-4873-974f-0a09e3ad62f0}</UniqueIdentifier>
+ <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="icmp.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="log.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="menu.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="options.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ping.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="pinggraph.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="pinglist.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="pingthread.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="rawping.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="utils.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="collection.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="common.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="icmp.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="log.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="menu.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="options.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ping.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="pinggraph.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="pinglist.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="pingthread.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="rawping.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="utils.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="green.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="grey.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="ico00001.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="icon1.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="icon2.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="icon3.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="red.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="yellow.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="ping.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/Ping/pinggraph.cpp b/plugins/Ping/pinggraph.cpp
new file mode 100644
index 0000000000..30d5d6c2df
--- /dev/null
+++ b/plugins/Ping/pinggraph.cpp
@@ -0,0 +1,325 @@
+#include "common.h"
+#include "pinggraph.h"
+
+HistoryMap history_map;
+
+#define ID_REPAINT_TIMER 10101
+
+struct WindowData {
+ DWORD item_id;
+ HistoryList list;
+ HWND hwnd_chk_grid;
+ HWND hwnd_chk_stat;
+ bool show_grid;
+ bool show_stat;
+};
+
+#define WM_REBUILDLIST (WM_USER + 5)
+
+LRESULT CALLBACK GraphWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_REBUILDLIST:
+ {
+ WindowData *wd = (WindowData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+ bool found = false;
+ EnterCriticalSection(&data_list_cs);
+ for(PINGLIST::Iterator i = data_list.start(); i.has_val(); i.next()) {
+ if(i.val().item_id == wd->item_id) {
+ wd->list = history_map[wd->item_id];
+ found = true;
+ break;
+ }
+ }
+ LeaveCriticalSection(&data_list_cs);
+
+ if(!found) {
+ PostMessage(hwnd, WM_CLOSE, 0, 0);
+ return TRUE;
+ }
+
+ InvalidateRect(hwnd, 0, FALSE);
+ }
+ return TRUE;
+ case WM_SHOWWINDOW:
+ if(wParam == TRUE && lParam == 0) {
+ WindowData *wd = (WindowData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+
+ if(wd->hwnd_chk_grid == 0) {
+ wd->hwnd_chk_grid = CreateWindow(_T("BUTTON"), TranslateT("Show grid lines"), WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, 0, 0, 0, 0, hwnd, 0, hInst, 0);
+ SendMessage(wd->hwnd_chk_grid, BM_SETCHECK, wd->show_grid ? BST_CHECKED : BST_UNCHECKED, 0);
+ }
+ if(wd->hwnd_chk_stat == 0) {
+ wd->hwnd_chk_stat = CreateWindow(_T("BUTTON"), TranslateT("Show stats"), WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, 0, 0, 0, 0, hwnd, 0, hInst, 0);
+ SendMessage(wd->hwnd_chk_stat, BM_SETCHECK, wd->show_stat ? BST_CHECKED : BST_UNCHECKED, 0);
+ }
+ KillTimer(hwnd, ID_REPAINT_TIMER);
+#ifdef min
+ SetTimer(hwnd, ID_REPAINT_TIMER, min(options.ping_period * 1000, 5000), 0);
+#else
+ SetTimer(hwnd, ID_REPAINT_TIMER, std::min(options.ping_period * 1000, 5000), 0);
+#endif
+
+ SendMessage(hwnd, WM_REBUILDLIST, 0, 0);
+ }
+ break;
+ case WM_COMMAND:
+ if(HIWORD(wParam) == BN_CLICKED) {
+ WindowData *wd = (WindowData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ if((HWND)lParam == wd->hwnd_chk_grid) {
+ wd->show_grid = (SendMessage(wd->hwnd_chk_grid, BM_GETCHECK, 0, 0) == BST_CHECKED);
+ } else if((HWND)lParam == wd->hwnd_chk_stat) {
+ wd->show_stat = (SendMessage(wd->hwnd_chk_stat, BM_GETCHECK, 0, 0) == BST_CHECKED);
+ }
+ InvalidateRect(hwnd, 0, TRUE);
+ }
+ return TRUE;
+ case WM_TIMER:
+ {
+ SendMessage(hwnd, WM_REBUILDLIST, 0, 0);
+ }
+ return TRUE;
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ HDC hdc;
+ RECT r;
+ WindowData *wd = (WindowData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ if(wd && (hdc = BeginPaint(hwnd, &ps)) != 0) {
+ GetClientRect(hwnd, &r);
+ FillRect(hdc, &r, GetSysColorBrush(COLOR_WINDOW));
+
+ short max_value = -1, min_value = (short)0x7FFF,
+ graph_height = 0; // this is minimum graph height, in ms
+ double avg = 0;
+ for(HistoryList::Iterator hli = wd->list.start(); hli.has_val(); hli.next()) {
+ if(hli.val().first > max_value) max_value = hli.val().first;
+ if(hli.val().first >= 0 && hli.val().first < min_value) min_value = hli.val().first;
+ avg += hli.val().first;
+ }
+ if(wd->list.size())
+ avg /= wd->list.size();
+
+ graph_height = (int)(max_value * 1.2f);
+ if(graph_height < MIN_GRAPH_HEIGHT) graph_height = MIN_GRAPH_HEIGHT;
+
+#ifdef max
+ float unit_width = (r.right - r.left) / (float)max((int)wd->list.size(), MIN_BARS), // space for at least MIN_BARS bars
+#else
+ float unit_width = (r.right - r.left) / (float)std::max((int)wd->list.size(), MIN_BARS), // space for at least MIN_BARS bars
+#endif
+ unit_height = (r.bottom - r.top) / (float)graph_height;
+
+ time_t last_time = 0, time, start_time = 0;
+ if(wd->list.size())
+ start_time = wd->list.start().val().second;
+
+ RECT bar;
+ bar.bottom = r.bottom;
+ float x = r.right - (unit_width * wd->list.size() + 0.5f);
+ bar.left = (int)(x + 0.5f);
+ bar.right = (int)(x + unit_width + 0.5f);
+
+ // set up pen for horiz (ping time) and vert (time covered by graph) lines
+ HPEN hPenOld, hPen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DDKSHADOW));
+ hPenOld = (HPEN)SelectObject(hdc, hPen);
+
+ for(HistoryList::Iterator hi = wd->list.start(); hi.has_val(); hi.next()) {
+ if(hi.val().first != -1) {
+ bar.top = bar.bottom - (int)(hi.val().first * unit_height + 0.5f);
+ FillRect(hdc, &bar, GetSysColorBrush(COLOR_HOTLIGHT));
+ }
+
+ time = hi.val().second - start_time;
+
+ if(time / MARK_PERIOD != last_time / MARK_PERIOD) { // new minute
+ MoveToEx(hdc, bar.left, r.bottom, 0);
+ LineTo(hdc, bar.left, r.top);
+ }
+
+ last_time = time;
+
+ x += unit_width;
+ bar.left = bar.right;
+ bar.right = (int)(x + unit_width + 0.5f);
+ }
+
+ if(wd->show_grid) {
+ // draw horizontal lines to mark every 100ms
+ for(int li = 0; li < graph_height; li += MARK_TIME) {
+ MoveToEx(hdc, r.left, r.bottom - (int)(li * unit_height + 0.5f), 0);
+ LineTo(hdc, r.right, r.bottom - (int)(li * unit_height + 0.5f));
+ }
+ }
+
+ HPEN hPen2 = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
+ if(wd->show_stat) {
+ SelectObject(hdc, hPen2);
+ MoveToEx(hdc, r.left, r.bottom - (int)(avg * unit_height + 0.5f), 0);
+ LineTo(hdc, r.right, r.bottom - (int)(avg * unit_height + 0.5f));
+ if(max_value != avg) {
+ MoveToEx(hdc, r.left, r.bottom - (int)(max_value * unit_height + 0.5f), 0);
+ LineTo(hdc, r.right, r.bottom - (int)(max_value * unit_height + 0.5f));
+ MoveToEx(hdc, r.left, r.bottom - (int)(min_value * unit_height + 0.5f), 0);
+ LineTo(hdc, r.right, r.bottom - (int)(min_value * unit_height + 0.5f));
+ }
+ }
+
+ // restore pen
+ SelectObject(hdc, hPenOld);
+ DeleteObject(hPen);
+ DeleteObject(hPen2);
+
+ SetBkMode(hdc, TRANSPARENT);
+ SetTextColor(hdc, GetSysColor(COLOR_3DDKSHADOW));
+ char buff[64];
+ if(wd->show_grid) {
+ sprintf(buff, Translate("%d ms"), MARK_TIME);
+ TextOut(hdc, r.right - 100, r.bottom - (int)(unit_height * MARK_TIME + 0.5f), buff, strlen(buff));
+ }
+
+ if(wd->show_stat) {
+ SetTextColor(hdc, RGB(255, 0, 0));
+ sprintf(buff, Translate("AVG %.1lf ms"), avg);
+ TextOut(hdc, r.left + 10, r.bottom - (int)(avg * unit_height + 0.5f), buff, strlen(buff));
+ if(max_value != avg) {
+ sprintf(buff, Translate("MAX %hd ms"), max_value);
+ TextOut(hdc, r.left + 10, r.bottom - (int)(max_value * unit_height + 0.5f), buff, strlen(buff));
+ sprintf(buff, Translate("MIN %hd ms"), min_value);
+ TextOut(hdc, r.left + 10, r.bottom - (int)(min_value * unit_height + 0.5f), buff, strlen(buff));
+ }
+ }
+
+ EndPaint(hwnd, &ps);
+ }
+ }
+ return TRUE;
+
+ case WM_ERASEBKGND:
+ return TRUE;
+
+ case WM_SIZE:
+ {
+ WindowData *wd = (WindowData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ RECT r;
+ GetClientRect(hwnd, &r);
+ if(wd->hwnd_chk_grid != 0) SetWindowPos(wd->hwnd_chk_grid, 0, r.right - 150, r.top + 10, 120, 20, SWP_NOZORDER | SWP_NOACTIVATE);
+ if(wd->hwnd_chk_stat != 0) SetWindowPos(wd->hwnd_chk_stat, 0, r.right - 150, r.top + 30, 120, 20, SWP_NOZORDER | SWP_NOACTIVATE);
+ }
+ InvalidateRect(hwnd, 0, FALSE);
+ break;
+ case WM_CLOSE:
+ {
+ KillTimer(hwnd, ID_REPAINT_TIMER);
+ WindowData *wd = (WindowData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ {
+ char buff[30];
+ sprintf(buff, "pinggraphwnd%d", wd->item_id);
+ Utils_SaveWindowPosition(hwnd, 0, PLUG, buff);
+ }
+ }
+ break;
+ case WM_DESTROY:
+ {
+ WindowData *wd = (WindowData *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ {
+ char buff[30];
+ sprintf(buff, "WindowHandle%d", wd->item_id);
+ DBWriteContactSettingDword(0, PLUG, buff, 0);
+ }
+ delete wd;
+ }
+ // drop through
+ };
+
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+INT_PTR ShowGraph(WPARAM wParam, LPARAM lParam) {
+ char buff[30];
+ sprintf(buff, "WindowHandle%d", (DWORD)wParam);
+ HWND hGraphWnd = (HWND)DBGetContactSettingDword(0, PLUG, buff, 0);
+ if(hGraphWnd) {
+ ShowWindow(hGraphWnd, SW_SHOW);
+ SetWindowPos(hGraphWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ return 0;
+ }
+
+ WNDCLASS wndclass;
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = GraphWindowProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = hInst;
+ wndclass.hIcon = hIconResponding;
+ wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
+ wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE+1);
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = _T(PLUG) _T("GraphWindow");
+ RegisterClass(&wndclass);
+
+ char title[256];
+ strcpy(title, "Ping Graph");
+ if(lParam) {
+ strcat(title, " - ");
+ strncat(title, (char *)lParam, 256 - 13);
+ }
+
+ HWND parent = 0;
+ hGraphWnd = CreateWindowEx(0, _T(PLUG) _T("GraphWindow"), title,
+ (WS_THICKFRAME | WS_CAPTION | WS_SYSMENU | WS_CLIPCHILDREN) & ~CS_VREDRAW & ~CS_HREDRAW,
+ 0,0,800,600,parent,NULL,hInst,NULL);
+
+ WindowData *wd = new WindowData;
+ wd->item_id = (DWORD)wParam; // wParam is destination id
+ wd->hwnd_chk_grid = 0;
+ wd->hwnd_chk_stat = 0;
+ wd->show_grid = DBGetContactSettingByte(0, PLUG, "ShowGridLines", 0) ? true : false;
+ wd->show_stat = DBGetContactSettingByte(0, PLUG, "ShowStats", 1) ? true : false;
+
+ DBWriteContactSettingDword(0, PLUG, buff, (DWORD)hGraphWnd);
+
+ SetWindowLongPtr(hGraphWnd, GWLP_USERDATA, (LONG_PTR)wd);
+
+ sprintf(buff, "pinggraphwnd%d", wd->item_id);
+ Utils_RestoreWindowPosition(hGraphWnd, 0, PLUG, buff);
+
+ if(!IsWindowVisible(hGraphWnd))
+ ShowWindow(hGraphWnd, SW_SHOW);
+
+ return 0;
+}
+
+// save window positions, close windows
+void graphs_cleanup() {
+ int list_size = GetListSize(0, 0);
+ char buff[64];
+ HWND hwnd;
+
+ for(int i = 0; i < list_size; i++) {
+ sprintf(buff, "WindowHandle%d", i);
+ if(hwnd = (HWND)DBGetContactSettingDword(0, PLUG, buff, 0)) {
+ DestroyWindow(hwnd);
+ DBWriteContactSettingDword(0, PLUG, buff, 0);
+ sprintf(buff, "WindowWasOpen%d", i);
+ DBWriteContactSettingByte(0, PLUG, buff, 1);
+ }
+ }
+}
+
+// remove old data, possibly left from a crash
+void graphs_init() {
+ PINGLIST pl;
+ char buff[64];
+ CallService(PLUG "/GetPingList", 0, (LPARAM)&pl);
+ for(PINGLIST::Iterator i = pl.start(); i.has_val(); i.next()) {
+ sprintf(buff, "WindowHandle%d", i.val().item_id); // clean up from possible crash
+ DBWriteContactSettingDword(0, PLUG, buff, 0);
+ sprintf(buff, "WindowWasOpen%d", i.val().item_id); // restore windows that were open on shutdown
+ if(DBGetContactSettingByte(0, PLUG, buff, 0)) {
+ DBWriteContactSettingByte(0, PLUG, buff, 0);
+ ShowGraph((WPARAM)i.val().item_id, (LPARAM)i.val().pszLabel);
+ }
+ }
+}
diff --git a/plugins/Ping/pinggraph.h b/plugins/Ping/pinggraph.h
new file mode 100644
index 0000000000..268b376a58
--- /dev/null
+++ b/plugins/Ping/pinggraph.h
@@ -0,0 +1,22 @@
+#ifndef _PINGGRAPH_H
+#define _PINGGRAPH_H
+
+#include "pinglist.h"
+#include "pingthread.h"
+
+#define MIN_GRAPH_HEIGHT 10 // minimum braph height, ms
+#define MIN_BARS 20 // space for at least this many bars
+#define MARK_PERIOD 3600 // vertical lines every this many secs (3600 == 1 hour)
+#define MARK_TIME 100 // horizontal lines every this many ms
+
+INT_PTR ShowGraph(WPARAM wParam, LPARAM lParam);
+
+// save window positions, close windows
+void graphs_cleanup();
+
+// restore windows that were open when cleanup was called last?
+void graphs_init();
+
+extern HistoryMap history_map;
+
+#endif
diff --git a/plugins/Ping/pinglist.cpp b/plugins/Ping/pinglist.cpp
new file mode 100644
index 0000000000..91d00f97af
--- /dev/null
+++ b/plugins/Ping/pinglist.cpp
@@ -0,0 +1,230 @@
+#include "common.h"
+#include "pinglist.h"
+
+#include "options.h"
+
+PINGLIST list_items;
+CRITICAL_SECTION list_cs;
+HANDLE reload_event_handle;
+
+DWORD NextID = 1;
+
+BOOL clist_handle_changing = FALSE;
+
+BOOL changing_clist_handle() {
+ return clist_handle_changing;
+}
+
+void set_changing_clist_handle(BOOL flag) {
+ clist_handle_changing = flag;
+}
+
+const bool PINGADDRESS::operator==(const PINGADDRESS &b) const {
+ return index == b.index;
+}
+
+const bool PINGADDRESS::operator<(const PINGADDRESS &b) const {
+ return index < b.index;
+}
+
+// lParam is address of pointer to a std::list<PINGADDRESS>
+// copies data into this structure
+INT_PTR GetPingList(WPARAM wParam,LPARAM lParam)
+{
+ PINGLIST *pa = (PINGLIST *)lParam;
+
+ EnterCriticalSection(&list_cs);
+ *pa = list_items;
+ LeaveCriticalSection(&list_cs);
+
+ return 0;
+}
+
+INT_PTR GetListSize(WPARAM wParam, LPARAM lParam) {
+ INT_PTR ret = 0;
+ EnterCriticalSection(&list_cs);
+ ret = list_items.size();
+ LeaveCriticalSection(&list_cs);
+ return ret;
+}
+
+void write_ping_address(PINGADDRESS *i) {
+ char buff[16];
+ sprintf(buff, "PING_DEST_%d", i->index);
+
+ if(i->item_id == 0) {
+ i->item_id = NextID++;
+ DBWriteContactSettingDword(0, PLUG, "NextID", NextID);
+ }
+
+ DBWriteContactSettingDword(0, buff, "Id", i->item_id);
+ DBWriteContactSettingString(0, buff, "Address", i->pszName);
+ DBWriteContactSettingString(0, buff, "Label", i->pszLabel);
+ DBWriteContactSettingWord(0, buff, "Status", i->status);
+ DBWriteContactSettingDword(0, buff, "Port", i->port);
+ DBWriteContactSettingString(0, buff, "Proto", i->pszProto);
+ if(strlen(i->pszCommand))
+ DBWriteContactSettingString(0, buff, "Command", i->pszCommand);
+ else
+ DBDeleteContactSetting(0, buff, "Command");
+ if(strlen(i->pszParams))
+ DBWriteContactSettingString(0, buff, "CommandParams", i->pszParams);
+ else
+ DBDeleteContactSetting(0, buff, "CommandParams");
+ DBWriteContactSettingWord(0, buff, "SetStatus", i->set_status);
+ DBWriteContactSettingWord(0, buff, "GetStatus", i->get_status);
+ DBWriteContactSettingWord(0, buff, "Index", i->index);
+}
+
+// call with list_cs locked
+void write_ping_addresses() {
+ int index = 0;
+ for(PINGLIST::Iterator i = list_items.start(); i.has_val(); i.next(), index++) {
+ i.val().index = index;
+ write_ping_address(&i.val());
+ }
+
+ // mark further destinations in the DB as invalid
+ char buff[16];
+ bool found;
+
+ do {
+ found = false;
+ sprintf(buff, "PING_DEST_%d", index++);
+ if(DBGetContactSettingDword(0, buff, "Id", 0) != 0) {
+ found = true;
+ DBWriteContactSettingDword(0, buff, "Id", 0);
+ }
+ } while(found);
+}
+
+bool read_ping_address(PINGADDRESS &pa) {
+ int index = pa.index;
+
+ char buff[16];
+ sprintf(buff, "PING_DEST_%d", index);
+
+ // return if not more contacts, or only deleted contacts remaining
+ if((pa.item_id = DBGetContactSettingDword(0, buff, "Id", 0)) == 0) return false;
+
+ DBVARIANT dbv;
+ if(!DBGetContactSetting(0, buff, "Address", &dbv)) {
+ strncpy(pa.pszName, dbv.pszVal, MAX_PINGADDRESS_STRING_LENGTH);
+ DBFreeVariant(&dbv);
+ } else return false;
+
+ if(!DBGetContactSetting(0, buff, "Label", &dbv)) {
+ strncpy(pa.pszLabel, dbv.pszVal, MAX_PINGADDRESS_STRING_LENGTH);
+ DBFreeVariant(&dbv);
+ } else return false;
+
+ pa.status = DBGetContactSettingWord(0, buff, "Status", PS_NOTRESPONDING);
+ if(pa.status != PS_DISABLED) pa.status = PS_NOTRESPONDING;
+
+ pa.port = (int)DBGetContactSettingDword(0, buff, "Port", -1);
+
+ if(!DBGetContactSetting(0, buff, "Proto", &dbv)) {
+ strncpy(pa.pszProto, dbv.pszVal, MAX_PINGADDRESS_STRING_LENGTH);
+ DBFreeVariant(&dbv);
+ } else pa.pszProto[0] = '\0';
+
+ if(!DBGetContactSetting(0, buff, "Command", &dbv)) {
+ strncpy(pa.pszCommand, dbv.pszVal, MAX_PATH);
+ DBFreeVariant(&dbv);
+ } else
+ pa.pszCommand[0] = '\0';
+ if(!DBGetContactSetting(0, buff, "CommandParams", &dbv)) {
+ strncpy(pa.pszParams, dbv.pszVal, MAX_PATH);
+ DBFreeVariant(&dbv);
+ } else
+ pa.pszParams[0] = '\0';
+
+ pa.set_status = DBGetContactSettingWord(0, buff, "SetStatus", ID_STATUS_ONLINE);
+ pa.get_status = DBGetContactSettingWord(0, buff, "GetStatus", ID_STATUS_OFFLINE);
+
+ pa.responding = false;
+ pa.round_trip_time = 0;
+ pa.miss_count = 0;
+ pa.index = DBGetContactSettingWord(0, buff, "Index", 0);
+
+ pa.index = index;
+ if(pa.item_id >= NextID) {
+ NextID = pa.item_id + 1;
+ DBWriteContactSettingDword(0, PLUG, "NextID", NextID);
+ }
+
+ return true;
+}
+
+// call with list_cs locked
+void read_ping_addresses() {
+ PINGADDRESS pa;
+
+ pa.index = 0;
+
+
+ list_items.clear();
+ while(read_ping_address(pa)) {
+ list_items.add(pa);
+ pa.index++;
+ }
+}
+
+INT_PTR LoadPingList(WPARAM wParam, LPARAM lParam) {
+ EnterCriticalSection(&list_cs);
+ read_ping_addresses();
+ LeaveCriticalSection(&list_cs);
+ NotifyEventHooks(reload_event_handle, 0, 0);
+ return 0;
+}
+
+// wParam is zero
+// lParam is zero
+INT_PTR SavePingList(WPARAM wParam, LPARAM lParam) {
+ EnterCriticalSection(&list_cs);
+ write_ping_addresses();
+ LeaveCriticalSection(&list_cs);
+ //NotifyEventHooks(reload_event_handle, 0, 0);
+
+ return 0;
+}
+
+// wParam is address of a PINGLIST structure to replace the current one
+// lParam is zero
+INT_PTR SetPingList(WPARAM wParam, LPARAM lParam) {
+ PINGLIST *pli = (PINGLIST *)wParam;
+
+ EnterCriticalSection(&list_cs);
+ list_items = *pli;
+ LeaveCriticalSection(&list_cs);
+ NotifyEventHooks(reload_event_handle, 0, 0);
+
+ return 0;
+}
+
+// wParam is address of a PINGLIST structure to replace the current one
+// lParam is zero
+INT_PTR SetAndSavePingList(WPARAM wParam, LPARAM lParam) {
+ PINGLIST *pli = (PINGLIST *)wParam;
+
+ EnterCriticalSection(&list_cs);
+
+ // set new list
+ list_items = *pli;
+ write_ping_addresses();
+ LeaveCriticalSection(&list_cs);
+
+ NotifyEventHooks(reload_event_handle, 0, 0);
+
+ return 0;
+}
+
+INT_PTR ClearPingList(WPARAM wParam, LPARAM lParam) {
+ EnterCriticalSection(&list_cs);
+ list_items.clear();
+ LeaveCriticalSection(&list_cs);
+
+ NotifyEventHooks(reload_event_handle, 0, 0);
+ return 0;
+}
+
diff --git a/plugins/Ping/pinglist.h b/plugins/Ping/pinglist.h
new file mode 100644
index 0000000000..ed2a94810f
--- /dev/null
+++ b/plugins/Ping/pinglist.h
@@ -0,0 +1,26 @@
+#ifndef _PINGLIST_H
+#define _PINGLIST_H
+
+typedef BinaryTree<PINGADDRESS> PINGLIST;
+
+#include <algorithm> // for sort
+
+extern PINGLIST list_items;
+extern HANDLE reload_event_handle;
+extern CRITICAL_SECTION list_cs;
+
+INT_PTR LoadPingList(WPARAM wParam, LPARAM lParam);
+INT_PTR GetPingList(WPARAM wParam,LPARAM lParam);
+INT_PTR SavePingList(WPARAM wParam, LPARAM lParam);
+INT_PTR SetPingList(WPARAM wParam, LPARAM lParam); // use when you modified db yourself
+INT_PTR SetAndSavePingList(WPARAM wParam, LPARAM lParam);
+INT_PTR ClearPingList(WPARAM wParam, LPARAM lParam);
+INT_PTR GetListSize(WPARAM wParam, LPARAM lParam);
+
+// only call with list_cs locked!
+void write_ping_addresses();
+
+
+BOOL changing_clist_handle();
+void set_changing_clist_handle(BOOL flag);
+#endif
diff --git a/plugins/Ping/pingthread.cpp b/plugins/Ping/pingthread.cpp
new file mode 100644
index 0000000000..5db0f4322e
--- /dev/null
+++ b/plugins/Ping/pingthread.cpp
@@ -0,0 +1,1063 @@
+#include "common.h"
+#include "pingthread.h"
+
+int upCount, total = 0;
+
+int list_size = 0;
+
+HANDLE mainThread;
+HANDLE hWakeEvent = 0;
+
+// thread protected variables
+CRITICAL_SECTION thread_finished_cs, list_changed_cs, data_list_cs;
+bool thread_finished = false, list_changed = false;
+PINGLIST data_list;
+
+HANDLE status_update_thread = 0;
+
+HWND hpwnd = 0, list_hwnd, hwnd_clist = 0;
+int frame_id = -1;
+
+HBRUSH tbrush = 0;
+
+FontID font_id;
+ColourID bk_col_id;
+HFONT hFont = 0;
+COLORREF bk_col = RGB(255, 255, 255);
+
+////////////////
+#define WinVerMajor() LOBYTE(LOWORD(GetVersion()))
+#define WinVerMinor() HIBYTE(LOWORD(GetVersion()))
+#define IsWinVer2000Plus() (WinVerMajor()>=5)
+
+static HMODULE hUserDll;
+BOOL (WINAPI *MySetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD);
+BOOL (WINAPI *MyAnimateWindow)(HWND hWnd,DWORD dwTime,DWORD dwFlags);
+#define TM_AUTOALPHA 1
+static int transparentFocus=1;
+/////////////////
+
+bool get_thread_finished() {
+ Lock(&thread_finished_cs, "get_thread_finished");
+ bool retval = thread_finished;
+ Unlock(&thread_finished_cs);
+ return retval;
+}
+
+void set_thread_finished(bool f) {
+ Lock(&thread_finished_cs, "set_thread_finished");
+ thread_finished = f;
+ Unlock(&thread_finished_cs);
+}
+
+bool get_list_changed() {
+ Lock(&list_changed_cs, "get_list_changed");
+ bool retval = list_changed;
+ Unlock(&list_changed_cs);
+ return retval;
+}
+
+void set_list_changed(bool f) {
+ Lock(&list_changed_cs, "set_list_changed");
+ list_changed = f;
+ Unlock(&list_changed_cs);
+}
+
+void SetProtoStatus(char *pszLabel, char *pszProto, int if_status, int new_status) {
+ if(strcmp(pszProto, Translate("<all>")) == 0) {
+ int num_protocols;
+ PROTOACCOUNT **pppDesc;
+
+ ProtoEnumAccounts(&num_protocols,&pppDesc);
+ for(int i = 0; i < num_protocols; i++) {
+ SetProtoStatus(pszLabel, pppDesc[i]->szModuleName, if_status, new_status);
+ }
+ } else {
+ char get_status[512], set_status[512];
+ mir_snprintf(get_status, 512, "%s%s", pszProto, PS_GETSTATUS);
+ if(ServiceExists(get_status)) {
+ mir_snprintf(set_status, 512, "%s%s", pszProto, PS_SETSTATUS);
+ if(CallService(get_status, 0, 0) == if_status) {
+ if(options.logging) {
+ char buf[1024];
+ mir_snprintf(buf, 1024, Translate("%s - setting status of protocol '%s' (%d)"), pszLabel, pszProto, new_status);
+ CallService(PLUG "/Log", (WPARAM)buf, 0);
+ }
+ CallService(set_status, new_status, 0);
+ }
+ }
+ }
+}
+
+DWORD WINAPI sttCheckStatusThreadProc( void *vp)
+{
+ clock_t start_t = clock(), end_t;
+ while(!get_thread_finished()) {
+
+ end_t = clock();
+
+ int wait = (int)((options.ping_period - ((end_t - start_t) / (double)CLOCKS_PER_SEC)) * 1000);
+ if(wait > 0)
+ WaitForSingleObjectEx(hWakeEvent, wait, TRUE);
+
+ if(get_thread_finished()) break;
+
+ start_t = clock();
+
+ bool timeout = false;
+ bool reply = false;
+ int count = 0;
+
+ PINGADDRESS pa;
+ HistPair history_entry;
+
+ Lock(&data_list_cs, "ping thread loop start");
+ set_list_changed(false);
+ int size = data_list.size();
+ Unlock(&data_list_cs);
+
+ int index = 0;
+ for(; index < size; index++) {
+ Lock(&data_list_cs, "ping thread loop start");
+ int c = 0;
+ for(PINGLIST::Iterator i = data_list.start(); i.has_val() && c <= index; i.next(), c++) {
+ if(c == index) {
+ // copy just what we need - i.e. not history, not command
+ pa.get_status = i.val().get_status;
+ pa.item_id = i.val().item_id;
+ pa.miss_count = i.val().miss_count;
+ pa.port = i.val().port;
+ strcpy(pa.pszLabel, i.val().pszLabel);
+ strcpy(pa.pszName, i.val().pszName);
+ strcpy(pa.pszProto, i.val().pszProto);
+ pa.set_status = i.val().set_status;
+ pa.status = i.val().status;
+ break;
+ }
+
+ }
+ Unlock(&data_list_cs);
+
+ if(get_thread_finished()) break;
+ if(get_list_changed()) break;
+
+ if(pa.status != PS_DISABLED) {
+ if(!options.no_test_icon) {
+ Lock(&data_list_cs, "ping thread loop start");
+ for(PINGLIST::Iterator i = data_list.start(); i.has_val(); i.next()) {
+ if(i.val().item_id == pa.item_id) {
+ i.val().status = PS_TESTING;
+ }
+ }
+ Unlock(&data_list_cs);
+ InvalidateRect(list_hwnd, 0, FALSE);
+ }
+
+ CallService(PLUG "/Ping", 0, (LPARAM)&pa);
+
+ if(get_thread_finished()) break;
+ if(get_list_changed()) break;
+
+ Lock(&data_list_cs, "ping thread loop start");
+ for(PINGLIST::Iterator i = data_list.start(); i.has_val(); i.next()) {
+ if(i.val().item_id == pa.item_id) {
+ i.val().responding = pa.responding;
+ i.val().round_trip_time = pa.round_trip_time;
+ history_entry.first = i.val().round_trip_time;
+ history_entry.second = time(0);
+ history_map[i.val().item_id].push_back(history_entry);
+ // maintain history (-1 represents no response)
+ while(history_map[i.val().item_id].size() >= MAX_HISTORY)
+ //history_map[i.val().item_id].pop_front();
+ history_map[i.val().item_id].remove(history_map[i.val().item_id].start().val());
+
+ if(pa.responding) {
+ if(pa.miss_count > 0)
+ pa.miss_count = -1;
+ else
+ pa.miss_count--;
+ pa.status = PS_RESPONDING;
+ }
+ else {
+ if(pa.miss_count < 0)
+ pa.miss_count = 1;
+ else
+ pa.miss_count++;
+ pa.status = PS_NOTRESPONDING;
+ }
+ i.val().miss_count = pa.miss_count;
+ i.val().status = pa.status;
+
+ break;
+ }
+ }
+ Unlock(&data_list_cs);
+
+ if(pa.responding) {
+ count++;
+
+ if(pa.miss_count == -1 - options.retries ||
+ (((-pa.miss_count) % (options.retries + 1)) == 0 && !options.block_reps))
+ {
+ reply = true;
+ if(options.show_popup2 && ServiceExists(MS_POPUP_SHOWMESSAGE)) {
+ ShowPopup("Ping Reply", pa.pszLabel, 1);
+ }
+ }
+ if(pa.miss_count == -1 - options.retries && options.logging) {
+ char buf[512];
+ mir_snprintf(buf, 512, Translate("%s - reply, %d"), pa.pszLabel, pa.round_trip_time);
+ CallService(PLUG "/Log", (WPARAM)buf, 0);
+ }
+ SetProtoStatus(pa.pszLabel, pa.pszProto, pa.get_status, pa.set_status);
+ } else {
+
+ if(pa.miss_count == 1 + options.retries ||
+ ((pa.miss_count % (options.retries + 1)) == 0 && !options.block_reps))
+ {
+ timeout = true;
+ if(options.show_popup && ServiceExists(MS_POPUP_SHOWMESSAGE)) {
+ ShowPopup("Ping Timeout", pa.pszLabel, 0);
+ }
+ }
+ if(pa.miss_count == 1 + options.retries && options.logging) {
+ char buf[512];
+ mir_snprintf(buf, 512, Translate("%s - timeout"), pa.pszLabel);
+ CallService(PLUG "/Log", (WPARAM)buf, 0);
+ }
+ }
+
+ InvalidateRect(list_hwnd, 0, FALSE);
+ }
+ }
+
+ if(timeout) SkinPlaySound("PingTimeout");
+ if(reply) SkinPlaySound("PingReply");
+
+ if(!get_list_changed()) {
+ upCount = count;
+ total = index;
+ } else {
+ total = 0;
+ }
+ }
+
+ return 0;
+}
+
+void start_ping_thread() {
+ DWORD tid;
+
+ if(status_update_thread) CloseHandle(status_update_thread);
+ status_update_thread = CreateThread(0, 0, sttCheckStatusThreadProc, 0, 0, &tid);
+}
+
+void stop_ping_thread() {
+ set_thread_finished(true);
+ SetEvent(hWakeEvent);
+ //ICMP::get_instance()->stop();
+ WaitForSingleObject(status_update_thread, 2000);
+ TerminateThread(status_update_thread, 0);
+ CloseHandle(status_update_thread);
+ status_update_thread = 0;
+}
+
+bool FrameIsFloating() {
+ if(frame_id == -1)
+ return true; // no frames, always floating
+
+ return (CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLOATING, frame_id), 0) != 0);
+}
+
+int FillList(WPARAM wParam, LPARAM lParam) {
+
+ if(options.logging)
+ CallService(PLUG "/Log", (WPARAM)"ping address list reload", 0);
+
+ PINGLIST pl;
+ CallService(PLUG "/GetPingList", 0, (LPARAM)&pl);
+
+ SendMessage(list_hwnd, WM_SETREDRAW, (WPARAM)FALSE, 0);
+ Lock(&data_list_cs, "fill_list");
+
+ data_list = pl;
+ SendMessage(list_hwnd, LB_RESETCONTENT, 0, 0);
+
+ int index = 0;
+ for(PINGLIST::Iterator j = data_list.start(); j.has_val(); j.next(), index++) {
+ SendMessage(list_hwnd, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)&j.val());
+ }
+ set_list_changed(true);
+
+ list_size = data_list.size();
+
+ Unlock(&data_list_cs);
+ SendMessage(list_hwnd, WM_SETREDRAW, (WPARAM)TRUE, 0);
+
+ InvalidateRect(list_hwnd, 0, FALSE);
+
+ SetEvent(hWakeEvent);
+
+ if(!ServiceExists(MS_CLIST_FRAMES_ADDFRAME) && options.attach_to_clist)
+ UpdateFrame();
+
+ return 0;
+}
+
+INT_PTR PingPlugShowWindow(WPARAM wParam, LPARAM lParam) {
+ if(hpwnd) {
+ if(frame_id != -1 && ServiceExists(MS_CLIST_FRAMES_SHFRAME)) CallService(MS_CLIST_FRAMES_SHFRAME, (WPARAM)frame_id, 0);
+ else {
+ ShowWindow(hpwnd, IsWindowVisible(hpwnd) ? SW_HIDE : SW_SHOW);
+ }
+ }
+ return 0;
+}
+
+#define TIMER_ID 11042
+void CALLBACK TimerProc(
+ HWND hwnd, // handle to window
+ UINT uMsg, // WM_TIMER message
+ UINT_PTR idEvent, // timer identifier
+ DWORD dwTime // current system time
+)
+{
+ if(frame_id != -1 && ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) {
+ char TBcapt[255];
+ if(total > 0)
+ wsprintf(TBcapt,"Ping (%d/%d)", upCount, total);
+ else
+ wsprintf(TBcapt,"Ping");
+
+ CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS,MAKEWPARAM(FO_TBNAME,frame_id),(LPARAM)TBcapt);
+ CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS,MAKEWPARAM(FO_TBTIPNAME,frame_id),(LPARAM)TBcapt);
+ CallService(MS_CLIST_FRAMES_UPDATEFRAME,frame_id,FU_TBREDRAW);
+ } else {
+// if(options.attach_to_clist) {
+// AttachToClist(true);
+// }
+ }
+}
+
+DWORD context_point;
+bool context_point_valid = false;
+LRESULT CALLBACK FrameWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ RECT rect;
+ MEASUREITEMSTRUCT *mis;
+ LPDRAWITEMSTRUCT dis;
+ SIZE textSize;
+ PINGADDRESS itemData;
+ RECT r;
+ LPARAM lp;
+ int sel;
+
+ switch(msg)
+ {
+
+ case WM_MEASUREITEM:
+ mis = (MEASUREITEMSTRUCT *)lParam;
+ mis->itemWidth = 100;
+ mis->itemHeight = options.row_height;
+ return TRUE;
+
+ case WM_DRAWITEM:
+ dis = (LPDRAWITEMSTRUCT)lParam;
+ if(dis->hwndItem == list_hwnd) {
+ HBRUSH ttbrush = 0;
+ COLORREF tcol;
+ if(dis->itemID != -1) {
+ Lock(&data_list_cs, "draw item");
+ itemData = *(PINGADDRESS *)dis->itemData;
+ Unlock(&data_list_cs);
+
+ SendMessage(list_hwnd, LB_SETITEMHEIGHT, 0, (LPARAM)options.row_height);
+ //dis->rcItem.bottom = dis->rcItem.top + options.row_height;
+
+ LONG x, y;
+ if(context_point_valid) {
+ RECT r;
+ GetWindowRect(list_hwnd, &r);
+ x = LOWORD(context_point) - r.left,
+ y = HIWORD(context_point) - r.top;
+ }
+
+ GetClientRect(hwnd, &r);
+
+ if((dis->itemState & ODS_SELECTED && dis->itemState & ODS_FOCUS)
+ || (context_point_valid && (x >= dis->rcItem.left && x <= dis->rcItem.right) && (y >= dis->rcItem.top && y <= dis->rcItem.bottom)))
+ {
+ tcol = DBGetContactSettingDword(NULL,"CLC","SelBkColour", GetSysColor(COLOR_HIGHLIGHT));
+ SetBkColor(dis->hDC, tcol);
+ FillRect(dis->hDC, &dis->rcItem, (ttbrush = CreateSolidBrush(tcol)));
+
+ tcol = DBGetContactSettingDword(NULL,"CLC","SelTextColour", GetSysColor(COLOR_HIGHLIGHTTEXT));
+ SetTextColor(dis->hDC, tcol);
+ } else {
+ tcol = bk_col;
+ SetBkColor(dis->hDC, tcol);
+ FillRect(dis->hDC, &dis->rcItem, (ttbrush = CreateSolidBrush(tcol)));
+
+ tcol = DBGetContactSettingDword(NULL, PLUG, "FontCol", GetSysColor(COLOR_WINDOWTEXT));
+ SetTextColor(dis->hDC, tcol);
+ }
+
+ SetBkMode(dis->hDC, TRANSPARENT);
+ HICON hIcon = (itemData.status != PS_DISABLED ? (itemData.status == PS_TESTING ? hIconTesting : (itemData.status == PS_RESPONDING ? hIconResponding : hIconNotResponding)) : hIconDisabled);
+ dis->rcItem.left += options.indent;
+ //DrawIconEx(dis->hDC,dis->rcItem.left,(dis->rcItem.top + dis->rcItem.bottom - GetSystemMetrics(SM_CYSMICON))>>1,hIcon,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL);
+ //DrawIconEx(dis->hDC,dis->rcItem.left,(dis->rcItem.top + dis->rcItem.bottom - GetSystemMetrics(SM_CYSMICON))>>1,hIcon,0, 0, 0, NULL, DI_NORMAL);
+ DrawIconEx(dis->hDC,dis->rcItem.left,dis->rcItem.top + ((options.row_height - 16)>>1),hIcon,0, 0, 0, NULL, DI_NORMAL);
+
+ GetTextExtentPoint32(dis->hDC,itemData.pszLabel,lstrlen(itemData.pszLabel),&textSize);
+ TextOut(dis->hDC,dis->rcItem.left + 16 + 4,(dis->rcItem.top + dis->rcItem.bottom - textSize.cy)>>1,itemData.pszLabel,lstrlen(itemData.pszLabel));
+
+ if(itemData.status != PS_DISABLED) {
+ char buf[256];
+ if(itemData.responding) {
+ mir_snprintf(buf, 256, Translate("%d ms"), itemData.round_trip_time);
+ GetTextExtentPoint32(dis->hDC,buf,lstrlen(buf),&textSize);
+ TextOut(dis->hDC,dis->rcItem.right - textSize.cx - 2,(dis->rcItem.top + dis->rcItem.bottom -textSize.cy)>>1,buf,lstrlen(buf));
+ } else if(itemData.miss_count > 0) {
+ mir_snprintf(buf, 256, "[%d]", itemData.miss_count);
+ GetTextExtentPoint32(dis->hDC,buf,lstrlen(buf),&textSize);
+ TextOut(dis->hDC,dis->rcItem.right - textSize.cx - 2,(dis->rcItem.top + dis->rcItem.bottom -textSize.cy)>>1,buf,lstrlen(buf));
+ }
+ }
+ SetBkMode(dis->hDC, OPAQUE);
+ }
+ if(ttbrush) DeleteObject(ttbrush);
+ return TRUE;
+ }
+ //return DefWindowProc(hwnd, msg, wParam, lParam);
+ return TRUE;
+
+ case WM_CTLCOLORLISTBOX:
+ {
+ if(tbrush) DeleteObject(tbrush);
+
+ return (BOOL)(tbrush = CreateSolidBrush(bk_col));
+ }
+
+ case WM_ERASEBKGND:
+ {
+ RECT r;
+ GetClientRect(hwnd, &r);
+ if(!tbrush) tbrush = CreateSolidBrush(bk_col);
+ FillRect((HDC)wParam, &r, tbrush);
+ }
+ return TRUE;
+
+ case WM_CONTEXTMENU:
+ {
+ context_point = lParam;
+ context_point_valid = true;
+ InvalidateRect(list_hwnd, 0, FALSE);
+ HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1)),
+ submenu = GetSubMenu(menu, 0);
+
+ POINT pt = {LOWORD(context_point),HIWORD(context_point)};
+
+ RECT r;
+ GetClientRect(list_hwnd, &r);
+ ScreenToClient(list_hwnd, &pt);
+
+ DWORD item = SendMessage(list_hwnd, LB_ITEMFROMPOINT, 0, MAKELPARAM(pt.x, pt.y));
+ bool found = false;
+ if(HIWORD(item) == 0) {
+ int count = LOWORD(item);
+ Lock(&data_list_cs, "show graph");
+ if(count >= 0 && count < (int)data_list.size()) {
+ itemData = *(PINGADDRESS *)SendMessage(list_hwnd, LB_GETITEMDATA, count, 0);
+ found = true;
+ }
+ Unlock(&data_list_cs);
+
+ }
+
+ if(found) {
+ EnableMenuItem(submenu, ID_MENU_GRAPH, MF_BYCOMMAND | MF_ENABLED);
+ EnableMenuItem(submenu, ID_MENU_EDIT, MF_BYCOMMAND | MF_ENABLED);
+ EnableMenuItem(submenu, ID_MENU_TOGGLE, MF_BYCOMMAND | MF_ENABLED);
+ if(itemData.status == PS_DISABLED) {
+ ModifyMenu(submenu, ID_MENU_TOGGLE, MF_BYCOMMAND | MF_STRING, ID_MENU_TOGGLE, TranslateT("Enable"));
+ } else {
+ ModifyMenu(submenu, ID_MENU_TOGGLE, MF_BYCOMMAND | MF_STRING, ID_MENU_TOGGLE, TranslateT("Disable"));
+ }
+ } else {
+ EnableMenuItem(submenu, ID_MENU_GRAPH, MF_BYCOMMAND | MF_GRAYED);
+ EnableMenuItem(submenu, ID_MENU_EDIT, MF_BYCOMMAND | MF_GRAYED);
+ EnableMenuItem(submenu, ID_MENU_TOGGLE, MF_BYCOMMAND | MF_GRAYED);
+ }
+
+ CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)submenu,0);
+
+ //ClientToScreen(list_hwnd, &pt);
+ GetCursorPos(&pt);
+ BOOL ret = TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, NULL);
+ DestroyMenu(menu);
+ if(ret) {
+ SendMessage(hwnd, WM_COMMAND, ret, 0);
+ }
+ context_point_valid = false;
+ InvalidateRect(list_hwnd, 0, FALSE);
+ }
+
+ return TRUE;
+
+ case WM_SYSCOLORCHANGE:
+ SendMessage(list_hwnd,msg,wParam,lParam);
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+
+ case WM_CREATE:
+ list_hwnd = CreateWindow("LISTBOX", "",
+ //(WS_VISIBLE | WS_CHILD | LBS_NOINTEGRALHEIGHT| LBS_STANDARD | WS_CLIPCHILDREN | LBS_OWNERDRAWVARIABLE | LBS_NOTIFY)
+ (WS_VISIBLE | WS_CHILD | LBS_STANDARD | LBS_OWNERDRAWFIXED | LBS_NOTIFY)
+ & ~WS_BORDER, 0, 0, 0, 0, hwnd, NULL, hInst,0);
+
+ if (DBGetContactSettingByte(NULL,"CList","Transparent",0))
+ {
+ if(ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) {
+
+ } else {
+#ifdef WS_EX_LAYERED
+ SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
+#endif
+#ifdef LWA_ALPHA
+ if (MySetLayeredWindowAttributes) MySetLayeredWindowAttributes(hwnd, RGB(0,0,0), (BYTE)DBGetContactSettingByte(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT), LWA_ALPHA);
+#endif
+ }
+ }
+
+ // timer to update titlebar
+ if(ServiceExists(MS_CLIST_FRAMES_ADDFRAME))
+ SetTimer(hwnd, TIMER_ID, 1000, TimerProc);
+
+ PostMessage(hwnd, WM_SIZE, 0, 0);
+ return TRUE;;
+
+ case WM_ACTIVATE:
+ if(wParam==WA_INACTIVE) {
+ if((HWND)wParam!=hwnd)
+ if(DBGetContactSettingByte(NULL,"CList","Transparent",SETTING_TRANSPARENT_DEFAULT))
+ if(transparentFocus)
+ SetTimer(hwnd, TM_AUTOALPHA,250,NULL);
+ }
+ else {
+ if(DBGetContactSettingByte(NULL,"CList","Transparent",SETTING_TRANSPARENT_DEFAULT)) {
+ KillTimer(hwnd,TM_AUTOALPHA);
+#ifdef LWA_ALPHA
+ if (MySetLayeredWindowAttributes) MySetLayeredWindowAttributes(hwnd, RGB(0,0,0), (BYTE)DBGetContactSettingByte(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT), LWA_ALPHA);
+#endif
+ transparentFocus=1;
+ }
+ }
+ return DefWindowProc(hwnd,msg,wParam,lParam);
+
+ case WM_SETCURSOR:
+ if(DBGetContactSettingByte(NULL,"CList","Transparent",SETTING_TRANSPARENT_DEFAULT)) {
+ if (!transparentFocus && GetForegroundWindow()!=hwnd && MySetLayeredWindowAttributes) {
+#ifdef LWA_ALPHA
+ MySetLayeredWindowAttributes(hwnd, RGB(0,0,0), (BYTE)DBGetContactSettingByte(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT), LWA_ALPHA);
+#endif
+ transparentFocus=1;
+ SetTimer(hwnd, TM_AUTOALPHA,250,NULL);
+ }
+ }
+ return DefWindowProc(hwnd,msg,wParam,lParam);
+
+ case WM_TIMER:
+ if ((int)wParam==TM_AUTOALPHA)
+ { int inwnd;
+
+ if (GetForegroundWindow()==hwnd) {
+ KillTimer(hwnd,TM_AUTOALPHA);
+ inwnd=1;
+ }
+ else {
+ POINT pt;
+ HWND hwndPt;
+ pt.x=(short)LOWORD(GetMessagePos());
+ pt.y=(short)HIWORD(GetMessagePos());
+ hwndPt=WindowFromPoint(pt);
+ inwnd=(hwndPt==hwnd || GetParent(hwndPt)==hwnd);
+ }
+ if (inwnd!=transparentFocus && MySetLayeredWindowAttributes)
+ { //change
+ transparentFocus=inwnd;
+#ifdef LWA_ALPHA
+ if(transparentFocus) MySetLayeredWindowAttributes(hwnd, RGB(0,0,0), (BYTE)DBGetContactSettingByte(NULL,"CList","Alpha",SETTING_ALPHA_DEFAULT), LWA_ALPHA);
+ else MySetLayeredWindowAttributes(hwnd, RGB(0,0,0), (BYTE)DBGetContactSettingByte(NULL,"CList","AutoAlpha",SETTING_AUTOALPHA_DEFAULT), LWA_ALPHA);
+#endif
+ }
+ if(!transparentFocus) KillTimer(hwnd,TM_AUTOALPHA);
+ return TRUE;
+ }
+ return FALSE;
+
+ case WM_SHOWWINDOW:
+ { static int noRecurse=0;
+ if(lParam) break;
+ if(noRecurse) break;
+ if(!DBGetContactSettingByte(NULL,"CLUI","FadeInOut",0) || !IsWinVer2000Plus()) break;
+#ifdef WS_EX_LAYERED
+ if(GetWindowLong(hwnd,GWL_EXSTYLE)&WS_EX_LAYERED) {
+ DWORD thisTick,startTick;
+ int sourceAlpha,destAlpha;
+ if(wParam) {
+ sourceAlpha=0;
+ destAlpha=(BYTE)DBGetContactSettingByte(NULL,"CList","Alpha",SETTING_AUTOALPHA_DEFAULT);
+#ifdef LWA_ALPHA
+ MySetLayeredWindowAttributes(hwnd, RGB(0,0,0), 0, LWA_ALPHA);
+#endif
+ noRecurse=1;
+ ShowWindow(hwnd,SW_SHOW);
+ noRecurse=0;
+ }
+ else {
+ sourceAlpha=(BYTE)DBGetContactSettingByte(NULL,"CList","Alpha",SETTING_AUTOALPHA_DEFAULT);
+ destAlpha=0;
+ }
+ for(startTick=GetTickCount();;) {
+ thisTick=GetTickCount();
+ if(thisTick>=startTick+200) break;
+#ifdef LWA_ALPHA
+ MySetLayeredWindowAttributes(hwnd, RGB(0,0,0), (BYTE)(sourceAlpha+(destAlpha-sourceAlpha)*(int)(thisTick-startTick)/200), LWA_ALPHA);
+#endif
+ }
+#ifdef LWA_ALPHA
+ MySetLayeredWindowAttributes(hwnd, RGB(0,0,0), (BYTE)destAlpha, LWA_ALPHA);
+#endif
+ }
+ else {
+// if(wParam) SetForegroundWindow(hwnd);
+ MyAnimateWindow(hwnd,200,AW_BLEND|(wParam?0:AW_HIDE));
+ //SetWindowPos(label,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_FRAMECHANGED);
+ }
+#endif
+ //int res = DefWindowProc(hwnd, msg, wParam, lParam);
+ //return res;
+ //break;
+ //return FALSE; //break;
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+
+ /*
+ case WM_PAINT:
+ {
+ paintDC = BeginPaint(hwnd, &paintStruct); //
+ //SelectObject(paintDC,TitleBarFont);
+ //SetBkMode(paintDC,TRANSPARENT);
+
+ //paintStruct.fErase=TRUE;
+ //color=RGB(1,1,1);
+ //brush=CreateSolidBrush(RGB(200,20,20));
+
+ //GetClientRect(hwnd,&rect);
+ //FillRect(paintDC,&rect,brush);
+ //TextOut(paintDC,4,4,"cl1 Bottom window",sizeof("cl1 Bottom window")-1);
+ //DeleteObject(brush);
+ EndPaint(hwnd, &paintStruct); //
+
+
+ };
+ return TRUE;
+
+ */
+ case WM_COMMAND:
+ //CreateServiceFunction("PingPlug/DisableAll", PingPlugDisableAll);
+ //CreateServiceFunction("PingPlug/EnableAll", PingPlugEnableAll);
+ switch(LOWORD(wParam)) {
+ case ID_MENU_GRAPH:
+ if(context_point_valid) {
+ WORD x = LOWORD(context_point),
+ y = HIWORD(context_point);
+ RECT r;
+ GetWindowRect(list_hwnd, &r);
+ DWORD item = SendMessage(list_hwnd, LB_ITEMFROMPOINT, 0, MAKELPARAM(x - r.left, y - r.top));
+ if(HIWORD(item) == 0) {
+ int count = LOWORD(item);
+ bool found = false;
+ Lock(&data_list_cs, "menu show graph");
+ if(count >= 0 && count < (int)data_list.size()) {
+ itemData = *(PINGADDRESS *)SendMessage(list_hwnd, LB_GETITEMDATA, count, 0);
+ found = true;
+ }
+ Unlock(&data_list_cs);
+ if(found)
+ CallService(PLUG "/ShowGraph", (WPARAM)itemData.item_id, (LPARAM)itemData.pszLabel);
+ }
+ }
+ return TRUE;
+ case ID_MENU_TOGGLE:
+ if(context_point_valid) {
+ WORD x = LOWORD(context_point),
+ y = HIWORD(context_point);
+ RECT r;
+ GetWindowRect(list_hwnd, &r);
+ DWORD item = SendMessage(list_hwnd, LB_ITEMFROMPOINT, 0, MAKELPARAM(x - r.left, y - r.top));
+ if(HIWORD(item) == 0) {
+ int count = LOWORD(item);
+ bool found = false;
+ Lock(&data_list_cs, "menu toggle");
+ if(count >= 0 && count < (int)data_list.size()) {
+ itemData = *(PINGADDRESS *)SendMessage(list_hwnd, LB_GETITEMDATA, count, 0);
+ found = true;
+ }
+ Unlock(&data_list_cs);
+ if(found)
+ CallService(PLUG "/ToggleEnabled", (WPARAM)itemData.item_id, 0);
+ }
+ }
+ return TRUE;
+ case ID_MENU_EDIT:
+ if(context_point_valid) {
+ WORD x = LOWORD(context_point),
+ y = HIWORD(context_point);
+ RECT r;
+ GetWindowRect(list_hwnd, &r);
+ DWORD item = SendMessage(list_hwnd, LB_ITEMFROMPOINT, 0, MAKELPARAM(x - r.left, y - r.top));
+ PINGADDRESS *temp = 0;
+ if(HIWORD(item) == 0) {
+ int count = LOWORD(item);
+ Lock(&data_list_cs, "menu edit");
+ if(count >= 0 && count < (int)data_list.size()) {
+ temp = (PINGADDRESS *)SendMessage(list_hwnd, LB_GETITEMDATA, count, 0);
+ }
+ Unlock(&data_list_cs);
+ if(temp) {
+ itemData = *temp;
+ if(Edit(hwnd, itemData)) {
+ Lock(&data_list_cs, "menu edited");
+ *temp = itemData;
+ CallService(PLUG "/SetAndSavePingList", (WPARAM)&data_list, 0);
+ Unlock(&data_list_cs);
+ }
+ }
+ }
+ }
+ return TRUE;
+ case ID_MENU_DISABLEALLPINGS:
+ CallService(PLUG "/DisableAll", 0, 0);
+ return TRUE;
+ case ID_MENU_ENABLEALLPINGS:
+ CallService(PLUG "/EnableAll", 0, 0);
+ return TRUE;
+ case ID_MENU_OPTIONS:
+ {
+ OPENOPTIONSDIALOG oop = {0};
+ oop.cbSize = sizeof(oop);
+ oop.pszGroup = "Network";
+ oop.pszPage = "PING";
+ oop.pszTab = "Settings";
+ Options_Open(&oop);
+ }
+ return TRUE;
+ case ID_MENU_DESTINATIONS:
+ {
+ OPENOPTIONSDIALOG oop = {0};
+ oop.cbSize = sizeof(oop);
+ oop.pszGroup = "Network";
+ oop.pszPage = "PING";
+ oop.pszTab = "Hosts";
+ Options_Open(&oop);
+ }
+ return TRUE;
+ }
+ if (HIWORD( wParam ) == LBN_DBLCLK) {
+ sel = SendMessage(list_hwnd, LB_GETCURSEL, 0, 0);
+ if(sel != LB_ERR) {
+ lp = SendMessage(list_hwnd, LB_GETITEMDATA, sel, 0);
+ if(lp != LB_ERR) {
+ PINGADDRESS *pItemData = (PINGADDRESS *)lp;
+
+ Lock(&data_list_cs, "command");
+
+ if(pItemData) {
+ DWORD item_id = pItemData->item_id;
+ Unlock(&data_list_cs);
+
+ int wake = CallService(PLUG "/DblClick", (WPARAM)item_id, 0);
+ InvalidateRect(list_hwnd, 0, FALSE);
+ if(wake) SetEvent(hWakeEvent);
+
+ if(options.logging) {
+ char buf[1024];
+ mir_snprintf(buf, 1024, "%s - %s", pItemData->pszLabel, (wake ? Translate("enabled") : Translate("double clicked")));
+ CallService(PLUG "/Log", (WPARAM)buf, 0);
+ }
+
+ } else {
+ Unlock(&data_list_cs);
+ }
+ }
+ }
+ return TRUE;
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+
+ case WM_MOVE: // needed for docked frames in clist_mw (not needed in clist_modern)
+ if(FrameIsFloating())
+ break;
+ case WM_SIZE:
+ {
+ //PostMessage(label, WM_SIZE, wParam, lParam);
+
+ GetClientRect(hwnd,&rect);
+ //SetWindowPos(list_hwnd, 0, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, SWP_NOZORDER);
+ //InvalidateRect(list_hwnd, &rect, FALSE);
+ int winheight = rect.bottom - rect.top,
+ itemheight = SendMessage(list_hwnd, LB_GETITEMHEIGHT, 0, 0),
+ count = SendMessage(list_hwnd, LB_GETCOUNT, 0, 0),
+#ifdef min
+ height = min(winheight - winheight % itemheight, itemheight * count);
+#else
+ height = std::min(winheight - winheight % itemheight, itemheight * count);
+#endif
+ SetWindowPos(list_hwnd, 0, rect.left, rect.top, rect.right-rect.left, height, SWP_NOZORDER);
+ InvalidateRect(list_hwnd, 0, FALSE);
+ }
+ InvalidateRect(hwnd, 0, TRUE);
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+
+ case WM_DESTROY:
+ if(!ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) {
+ Utils_SaveWindowPosition(hwnd, 0, PLUG, "main_window");
+ }
+
+ KillTimer(hwnd, TIMER_ID);
+ if(tbrush) DeleteObject(tbrush);
+
+ DestroyWindow(list_hwnd);
+
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+
+ case WM_CLOSE:
+ if(!ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) {
+ Utils_SaveWindowPosition(hwnd, 0, PLUG, "main_window");
+ ShowWindow(hwnd, SW_HIDE);
+ return 0;
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+/*
+ case WM_POWERBROADCAST:
+
+ if(options.logging) {
+ std::ostringstream oss;
+ switch(wParam) {
+ case PBT_APMSUSPEND:
+ CallService("PingPlug/Log", (WPARAM)"system suspend", 0);
+ break;
+ case PBT_APMRESUMESUSPEND:
+ oss << "system resume";
+ if(lParam == PBTF_APMRESUMEFROMFAILURE)
+ oss << " [suspend failure!]";
+ CallService("PingPlug/Log", (WPARAM)oss.str().c_str(), 0);
+ break;
+ case PBT_APMRESUMEAUTOMATIC:
+ oss << "system resume (automatic)";
+ if(lParam == PBTF_APMRESUMEFROMFAILURE)
+ oss << " [suspend failure!]";
+ CallService("PingPlug/Log", (WPARAM)oss.str().c_str(), 0);
+ break;
+ case PBT_APMRESUMECRITICAL:
+ oss << "system resume (critical)";
+ if(lParam == PBTF_APMRESUMEFROMFAILURE)
+ oss << " [suspend failure!]";
+ CallService("PingPlug/Log", (WPARAM)oss.str().c_str(), 0);
+ break;
+ }
+ }
+ break;
+*/
+ default:
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+
+ };
+
+ return(TRUE);
+};
+
+
+int ReloadFont(WPARAM wParam, LPARAM lParam) {
+ if(hFont) DeleteObject(hFont);
+
+ LOGFONT log_font;
+ CallService(MS_FONT_GET, (WPARAM)&font_id, (LPARAM)&log_font);
+ hFont = CreateFontIndirect(&log_font);
+ SendMessage(list_hwnd, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE);
+
+ bk_col = CallService(MS_COLOUR_GET, (WPARAM)&bk_col_id, 0);
+ RefreshWindow(0, 0);
+
+ return 0;
+}
+
+int RefreshWindow(WPARAM wParam, LPARAM lParam) {
+ InvalidateRect(list_hwnd, 0, TRUE);
+ InvalidateRect(hpwnd, 0, TRUE);
+ return 0;
+}
+
+void UpdateFrame() {
+ if(IsWindowVisible(hwnd_clist) != IsWindowVisible(hpwnd))
+ ShowWindow(hpwnd, IsWindowVisible(hwnd_clist) ? SW_SHOW : SW_HIDE);
+
+ if(!IsWindowVisible(hpwnd)) return;
+
+ RECT r_clist;
+ GetWindowRect(hwnd_clist, &r_clist);
+ RECT r_frame;
+ GetWindowRect(hpwnd, &r_frame);
+ int height = list_size * options.row_height;
+ if(GetWindowLong(hpwnd, GWL_STYLE) & WS_BORDER) {
+ RECT r_frame_client;
+ GetClientRect(hpwnd, &r_frame_client);
+ height += (r_frame.bottom - r_frame.top) - (r_frame_client.bottom - r_frame_client.top);
+ }
+
+ SetWindowPos(hpwnd, 0, r_clist.left, r_clist.top - height, (r_clist.right - r_clist.left), height, SWP_NOZORDER | SWP_NOACTIVATE);
+}
+
+WNDPROC wpOrigClistProc;
+
+// Subclass procedure
+LRESULT APIENTRY ClistSubclassProc(
+ HWND hwnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ if(uMsg == WM_SIZE || uMsg == WM_MOVE)
+ UpdateFrame();
+
+ if(uMsg == WM_NCCALCSIZE) { // possible window style change
+ if(GetWindowLong(hwnd_clist, GWL_STYLE) != GetWindowLong(hpwnd, GWL_STYLE)
+ || GetWindowLong(hwnd_clist, GWL_STYLE) != GetWindowLong(hpwnd, GWL_STYLE))
+ {
+ SetWindowLong(hpwnd, GWL_STYLE, GetWindowLong(hwnd_clist, GWL_STYLE));
+ SetWindowLong(hpwnd, GWL_EXSTYLE, GetWindowLong(hwnd_clist, GWL_EXSTYLE));
+ SetWindowPos(hpwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
+ }
+ }
+
+ if(uMsg == WM_SHOWWINDOW) {
+ ShowWindow(hpwnd, wParam);
+ }
+
+ return CallWindowProc(wpOrigClistProc, hwnd, uMsg, wParam, lParam);
+}
+
+void AttachToClist(bool attach) {
+ if(!hpwnd) return;
+
+ if(attach) {
+ SetWindowLong(hpwnd, GWL_STYLE, GetWindowLong(hwnd_clist, GWL_STYLE));
+ SetWindowLong(hpwnd, GWL_EXSTYLE, GetWindowLong(hwnd_clist, GWL_EXSTYLE));
+ SetWindowPos(hpwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
+
+ // subclass clist to trap move/size
+ wpOrigClistProc = (WNDPROC) SetWindowLongPtr(hwnd_clist, GWLP_WNDPROC, (LONG_PTR) ClistSubclassProc);
+
+ UpdateFrame();
+ } else {
+ SetWindowLong(hpwnd, GWL_STYLE, (WS_POPUPWINDOW | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_VISIBLE | WS_CLIPCHILDREN));
+ SetWindowLong(hpwnd, GWL_EXSTYLE, WS_EX_TOOLWINDOW);
+ SetWindowPos(hpwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
+
+ SetWindowLongPtr(hwnd_clist, GWLP_WNDPROC, (LONG_PTR) wpOrigClistProc);
+ }
+}
+
+void InitList() {
+
+ hUserDll = LoadLibrary(_T("user32.dll"));
+ if (hUserDll) {
+ MySetLayeredWindowAttributes = (BOOL (WINAPI *)(HWND,COLORREF,BYTE,DWORD))GetProcAddress(hUserDll, "SetLayeredWindowAttributes");
+ MyAnimateWindow=(BOOL (WINAPI*)(HWND,DWORD,DWORD))GetProcAddress(hUserDll,"AnimateWindow");
+ }
+
+ hwnd_clist = (HWND)CallService(MS_CLUI_GETHWND, 0, 0);
+
+ WNDCLASS wndclass;
+
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = FrameWindowProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = hInst;
+ wndclass.hIcon = hIconResponding;
+ wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
+ wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE+1);
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = PLUG "WindowClass";
+ RegisterClass(&wndclass);
+
+ if(ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) {
+ hpwnd=CreateWindow(PLUG "WindowClass", "Ping", (WS_BORDER | WS_CHILD | WS_CLIPCHILDREN), 0, 0, 0, 0, hwnd_clist, NULL, hInst, NULL);
+
+ CLISTFrame frame = {0};
+ frame.name=PLUG;
+ frame.cbSize=sizeof(CLISTFrame);
+ frame.hWnd=hpwnd;
+ frame.align=alBottom;
+ frame.Flags=F_VISIBLE|F_SHOWTB|F_SHOWTBTIP;
+ frame.height=30;
+ frame.TBname=Translate("Ping");
+
+ frame_id=CallService(MS_CLIST_FRAMES_ADDFRAME,(WPARAM)&frame,0);
+ } else {
+ hpwnd=CreateWindowEx(WS_EX_TOOLWINDOW, PLUG "WindowClass","Ping",
+ (WS_POPUPWINDOW | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_CLIPCHILDREN),
+ 0,0,400,300,hwnd_clist,NULL,hInst,NULL);
+
+ Utils_RestoreWindowPosition(hpwnd, 0, PLUG, "main_window");
+
+ CreateServiceFunction(PLUG "/ShowWindow", PingPlugShowWindow);
+
+ CLISTMENUITEM mi = {0};
+
+ mi.flags = CMIF_TCHAR;
+ mi.popupPosition = 1000200001;
+ mi.ptszPopupName = LPGENT( "Ping" );
+ mi.cbSize = sizeof( mi );
+ mi.position = 3000320001;
+ mi.hIcon = 0;//LoadIcon( hInst, 0);
+ mi.ptszName = LPGENT( "Show/Hide &Ping Window" );
+ mi.pszService = PLUG "/ShowWindow";
+ Menu_AddMainMenuItem(&mi);
+
+ if(options.attach_to_clist) AttachToClist(true);
+ else ShowWindow(hpwnd, SW_SHOW);
+ }
+
+ {
+ font_id.cbSize = sizeof(FontID);
+ strncpy(font_id.group, "Ping", sizeof(font_id.group));
+ strncpy(font_id.name, "List", sizeof(font_id.name));
+ strncpy(font_id.dbSettingsGroup, "PING", sizeof(font_id.dbSettingsGroup));
+ strncpy(font_id.prefix, "Font", sizeof(font_id.prefix));
+ font_id.order = 0;
+
+ FontRegister(&font_id);
+
+ bk_col_id.cbSize = sizeof(ColourID);
+ strncpy(bk_col_id.group, "Ping", sizeof(bk_col_id.group));
+ strncpy(bk_col_id.name, "Background", sizeof(bk_col_id.name));
+ strncpy(bk_col_id.dbSettingsGroup, "PING", sizeof(bk_col_id.dbSettingsGroup));
+ strncpy(bk_col_id.setting, "BgColor", sizeof(bk_col_id.setting));
+ ColourRegister(&bk_col_id);
+
+ HookEvent(ME_FONT_RELOAD, ReloadFont);
+
+ ReloadFont(0, 0);
+ }
+
+ start_ping_thread();
+}
+
+void DeinitList() {
+ DestroyWindow(hpwnd);
+ stop_ping_thread();
+ if(hFont) DeleteObject(hFont);
+} \ No newline at end of file
diff --git a/plugins/Ping/pingthread.h b/plugins/Ping/pingthread.h
new file mode 100644
index 0000000000..eda6dae61f
--- /dev/null
+++ b/plugins/Ping/pingthread.h
@@ -0,0 +1,27 @@
+#ifndef _PINGTHREAD_H
+#define _PINGTHREAD_H
+
+#include "pinglist.h"
+#include "pinggraph.h"
+#include "utils.h"
+#include "options.h"
+
+extern HANDLE mainThread;
+extern HANDLE hWakeEvent;
+extern CRITICAL_SECTION thread_finished_cs, list_changed_cs, data_list_cs;
+
+extern PINGLIST data_list;
+
+int FillList(WPARAM wParam, LPARAM lParam);
+
+int RefreshWindow(WPARAM wParam, LPARAM lParam);
+
+void UpdateFrame();
+void AttachToClist(bool attach);
+
+void InitList();
+void DeinitList();
+
+#endif
+
+
diff --git a/plugins/Ping/rawping.cpp b/plugins/Ping/rawping.cpp
new file mode 100644
index 0000000000..c5289dd16f
--- /dev/null
+++ b/plugins/Ping/rawping.cpp
@@ -0,0 +1,217 @@
+#include "common.h"
+#include "rawping.h"
+
+//#define _WSPIAPI_COUNTOF
+#ifndef _MSC_VER
+#include <ws2tcpip.h>
+#endif
+
+USHORT ip_checksum(USHORT* buffer, int size)
+{
+ unsigned long cksum = 0;
+
+ // Sum all the words together, adding the final byte if size is odd
+ while (size > 1) {
+ cksum += *buffer++;
+ size -= sizeof(USHORT);
+ }
+ if (size) {
+ cksum += *(UCHAR*)buffer;
+ }
+
+ // Do a little shuffling
+ cksum = (cksum >> 16) + (cksum & 0xffff);
+ cksum += (cksum >> 16);
+
+ // Return the bitwise complement of the resulting mishmash
+ return (USHORT)(~cksum);
+}
+
+SOCKET sd = -1;
+char packet[1024];
+char recv_buff[1024];
+USHORT seq_no = 0;
+bool inited = false;
+
+extern int init_raw_ping() {
+ WSAData wsaData;
+ if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
+ WSACleanup();
+ return 1;
+ }
+
+ if(sd != -1)
+ closesocket(sd);
+
+ // Create the socket
+ //sd = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, 0, 0, 0);
+ sd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+ if (sd == INVALID_SOCKET) {
+ return 2;
+ }
+
+ int ttl = 255;
+ if (setsockopt(sd, IPPROTO_IP, IP_TTL, (const char*)&ttl, sizeof(ttl)) == SOCKET_ERROR) {
+ return 3;
+ }
+
+ int our_recv_timeout = 100; // so we ca do multiple recv calls
+ if(setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&our_recv_timeout, sizeof(int)) == SOCKET_ERROR) {
+ return 4;
+ }
+
+
+ ICMPHeader *header = (ICMPHeader *)packet;
+ header->type = PT_ICMP_ECHO_REQUEST;
+ header->code = 0;
+ header->id = (USHORT)GetCurrentProcessId();
+
+ inited = true;
+ if(raw_ping("127.0.0.1", 500) >= 0) {
+ return 0;
+ }
+
+ inited = false;
+ return 5;
+}
+
+extern int raw_ping(char *host, int timeout) {
+ if(!inited) return -1;
+
+ // Initialize the destination host info block
+ sockaddr_in dest;
+ memset(&dest, 0, sizeof(dest));
+
+ // Turn first passed parameter into an IP address to ping
+ unsigned int addr = inet_addr(host);
+ if (addr != INADDR_NONE) {
+ // It was a dotted quad number, so save result
+ dest.sin_addr.s_addr = addr;
+ dest.sin_family = AF_INET;
+ }
+ else {
+ // Not in dotted quad form, so try and look it up
+ hostent* hp = gethostbyname(host);
+ if (hp != 0) {
+ // Found an address for that host, so save it
+ memcpy(&(dest.sin_addr), hp->h_addr, hp->h_length);
+ //dest.sin_family = hp->h_addrtype;
+ dest.sin_family = AF_INET;
+ }
+ else {
+ // Not a recognized hostname either!
+ if(options.logging) CallService(PLUG "/Log", (WPARAM)"rawping error: unrecognised host", 0);
+ return -1;
+ }
+ }
+
+ ICMPHeader *header = (ICMPHeader *)packet;
+ header->seq = ++seq_no;
+ header->checksum = 0;
+ header->checksum = ip_checksum((USHORT*)header, sizeof(ICMPHeader));
+
+ bool use_hi_res = false;
+ LARGE_INTEGER hr_freq, hr_send_time;
+ DWORD send_time;
+ if(QueryPerformanceFrequency(&hr_freq)) {
+ use_hi_res = true;
+ QueryPerformanceCounter(&hr_send_time);
+ } else
+ send_time = GetTickCount();
+
+ // send packet
+ int bwrote = sendto(sd, (char*)packet, sizeof(ICMPHeader), 0, (sockaddr*)&dest, sizeof(dest));
+ if (bwrote == SOCKET_ERROR) {
+ if(options.logging) CallService(PLUG "/Log", (WPARAM)"rawping error: unable to send", 0);
+ return -1;
+ }
+
+ // Wait for the ping reply
+ sockaddr_in source;
+ int fromlen = sizeof(source);
+ IPHeader *reply_header = (IPHeader *)recv_buff;
+ ICMPHeader *reply;
+ DWORD start, current_time;
+ LARGE_INTEGER hr_start, hr_current_time, hr_timeout;
+ if(use_hi_res) {
+ hr_timeout.QuadPart = (timeout * hr_freq.QuadPart / 1000);
+ QueryPerformanceCounter(&hr_start);
+ hr_current_time = hr_start;
+ } else {
+ start = GetTickCount();
+ current_time = start;
+ }
+
+ while(((use_hi_res && (hr_current_time.QuadPart < hr_start.QuadPart + hr_timeout.QuadPart))
+ || (!use_hi_res && current_time < start + timeout)))
+ {
+ int bread = recvfrom(sd, recv_buff, 1024, 0, (sockaddr*)&source, &fromlen);
+
+ if(use_hi_res)
+ QueryPerformanceCounter(&hr_current_time);
+ else
+ current_time = GetTickCount();
+
+ if (bread == SOCKET_ERROR) {
+ if(WSAGetLastError() != WSAETIMEDOUT) {
+ if(options.logging) CallService(PLUG "/Log", (WPARAM)"rawping error: socket error...cycling", 0);
+ }
+ continue;
+ }
+
+ if(reply_header->proto != ICMP_PROTO)
+ if(options.logging) CallService(PLUG "/Log", (WPARAM)"rawping error: packet not ICMP...cycling", 0);
+ continue;
+
+ if(reply_header->tos != 0)
+ if(options.logging) CallService(PLUG "/Log", (WPARAM)"rawping error: TOS not 0...cycling", 0);
+ continue;
+
+ reply = (ICMPHeader *)(recv_buff + reply_header->h_len * 4);
+ if((unsigned)bread < reply_header->h_len * 4 + sizeof(ICMPHeader)) {
+ if(options.logging) CallService(PLUG "/Log", (WPARAM)"rawping error: short header", 0);
+ continue;
+ }
+
+ if(reply->id != (USHORT)GetCurrentProcessId())
+ if(options.logging) CallService(PLUG "/Log", (WPARAM)"rawping error: wrong ID...cycling", 0);
+ continue;
+
+ if(reply->type != PT_ICMP_ECHO_REPLY && reply->type != PT_ICMP_SOURCE_QUENCH) {
+ if(options.logging) CallService(PLUG "/Log", (WPARAM)"rawping error: wrong type...cycling", 0);
+ continue;
+ }
+
+ //if(reply->seq < seq_no) continue;
+ //if(reply->seq > seq_no) return -1;
+ if(reply->seq != seq_no) {
+ if(options.logging) CallService(PLUG "/Log", (WPARAM)"rawping error: wrong sequence number...cycling", 0);
+ continue;
+ }
+
+ if(reply->type == PT_ICMP_SOURCE_QUENCH) {
+ char buff[1024];
+ sprintf(buff, Translate("Host %s requests that you reduce the amount of traffic you are sending."), host);
+ MessageBox(0, buff, Translate(PLUG " Warning"), MB_OK | MB_ICONWARNING);
+ }
+
+ if(use_hi_res) {
+ LARGE_INTEGER ticks;
+ ticks.QuadPart = hr_current_time.QuadPart - hr_send_time.QuadPart;
+ return (int)(ticks.QuadPart * 1000 / hr_freq.QuadPart);
+ } else
+ return current_time - send_time;
+ }
+ if(options.logging) CallService(PLUG "/Log", (WPARAM)"rawping error: timeout", 0);
+
+ return -1;
+}
+
+extern int cleanup_raw_ping() {
+ if(inited) {
+ closesocket(sd);
+ sd = -1;
+ WSACleanup();
+ }
+ return 0;
+}
diff --git a/plugins/Ping/rawping.h b/plugins/Ping/rawping.h
new file mode 100644
index 0000000000..23d9df1d61
--- /dev/null
+++ b/plugins/Ping/rawping.h
@@ -0,0 +1,61 @@
+#ifndef _RAWPING_H
+#define _RAWPING_H
+
+#include "options.h"
+#include "log.h"
+
+
+// ICMP protocol identifier
+#define ICMP_PROTO 1
+
+// ICMP packet types
+#define PT_ICMP_ECHO_REPLY 0
+#define PT_ICMP_DEST_UNREACH 3
+#define PT_ICMP_TTL_EXPIRE 11
+#define PT_ICMP_ECHO_REQUEST 8
+#define PT_ICMP_SOURCE_QUENCH 4
+
+// Minimum ICMP packet size, in bytes
+#define ICMP_MIN 8
+
+#ifdef _MSC_VER
+// The following two structures need to be packed tightly, but unlike
+// Borland C++, Microsoft C++ does not do this by default.
+#pragma pack(1)
+#endif
+
+// The IP header
+struct IPHeader {
+ BYTE h_len:4; // Length of the header in dwords
+ BYTE version:4; // Version of IP
+ BYTE tos; // Type of service
+ USHORT total_len; // Length of the packet in dwords
+ USHORT ident; // unique identifier
+ USHORT flags; // Flags
+ BYTE ttl; // Time to live
+ BYTE proto; // Protocol number (TCP, UDP etc)
+ USHORT checksum; // IP checksum
+ ULONG source_ip;
+ ULONG dest_ip;
+};
+
+// ICMP header
+struct ICMPHeader {
+ BYTE type; // ICMP packet type
+ BYTE code; // Type sub code
+ USHORT checksum;
+ USHORT id;
+ USHORT seq;
+};
+
+#ifdef _MSC_VER
+#pragma pack()
+#endif
+
+extern USHORT ip_checksum(USHORT* buffer, int size);
+
+extern int init_raw_ping();
+extern int raw_ping(char *host, int timeout);
+extern int cleanup_raw_ping();
+
+#endif
diff --git a/plugins/Ping/red.ico b/plugins/Ping/red.ico
new file mode 100644
index 0000000000..9c0c7c5a77
--- /dev/null
+++ b/plugins/Ping/red.ico
Binary files differ
diff --git a/plugins/Ping/resource.h b/plugins/Ping/resource.h
new file mode 100644
index 0000000000..214edade09
--- /dev/null
+++ b/plugins/Ping/resource.h
@@ -0,0 +1,80 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by ping.rc
+//
+#define IDD_DIALOG1 101
+#define IDD_DIALOG2 102
+#define IDD_DIALOG3 103
+#define IDR_MENU1 106
+#define IDI_ICON_PROTO 108
+#define IDI_ICON_DISABLED 112
+#define IDI_ICON_NOTRESPONDING 113
+#define IDI_ICON_RESPONDING 114
+#define IDI_ICON_TESTING 115
+#define IDC_PPM 1001
+#define IDC_PT 1002
+#define IDC_RPT 1003
+#define IDC_CHECK1 1005
+#define IDC_CHECKPOPUP 1005
+#define IDC_CHK_DESTTCP 1005
+#define IDC_BUTTONEDIT 1006
+#define IDC_BUTTONRELOAD 1007
+#define IDC_CHK_LOG 1008
+#define IDC_ED_FILENAME 1009
+#define IDC_CHECKPOPUP2 1010
+#define IDC_CHK_LOGCSV 1011
+#define IDC_CHK_BLOCK 1012
+#define IDC_BTN_VIEWLOG 1013
+#define IDC_ED_DATAFILENAME 1014
+#define IDC_BTN_LOGBROWSE 1015
+#define IDC_BTN_DATABROWSE 1016
+#define IDC_ED_DESTADDR 1016
+#define IDC_ED_DESTLAB 1017
+#define IDC_BTN_DESTADD 1018
+#define IDC_LST_DEST 1019
+#define IDC_BTN_DESTREM 1020
+#define IDC_ED_DESTPORT 1021
+#define IDC_BTN_DESTEDIT 1021
+#define IDC_ED_DESTPROTO 1022
+#define IDC_BTN_DESTUP 1022
+#define IDC_BTN_DESTDOWN 1023
+#define IDC_COMBO_DESTPROTO 1024
+#define IDC_COMBO_DESTSTAT 1025
+#define IDC_COMBO_DESTSTAT2 1026
+#define IDC_BGCOL 1031
+#define IDC_ED_COMMAND 1032
+#define IDC_STATFS 1032
+#define IDC_RSTATUS 1033
+#define IDC_ED_PARAMS 1033
+#define IDC_NRSTATUS 1034
+#define IDC_TSTATUS 1035
+#define IDC_EDIT1 1035
+#define IDC_DSTATUS 1036
+#define IDC_CHK_NOTESTSTATUS 1037
+#define IDC_CHK_NOTESTICON 1037
+#define IDC_COMBO_GROUP 1038
+#define IDC_CHK_HIDEPROTO 1038
+#define IDC_SP_INDENT 1038
+#define IDC_EDIT2 1039
+#define IDC_SP_ROWHEIGHT 1040
+#define IDC_CHK_ATTACH 1041
+#define IDC_CHK_MINMAX 1042
+#define IDC_ST_VER 1043
+#define ID_MENU_ENABLEALLPINGS 40002
+#define ID_MENU_OPTIONS 40003
+#define ID_MENU_DISABLEALLPINGS 40004
+#define ID_MENU_DESTINATIONS 40005
+#define ID_MENU_GRAPH 40006
+#define ID_MENU_TOGGLE 40007
+#define ID_MENU_EDIT 40008
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 116
+#define _APS_NEXT_COMMAND_VALUE 40009
+#define _APS_NEXT_CONTROL_VALUE 1044
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/Ping/utils.cpp b/plugins/Ping/utils.cpp
new file mode 100644
index 0000000000..faf65423de
--- /dev/null
+++ b/plugins/Ping/utils.cpp
@@ -0,0 +1,374 @@
+#include "common.h"
+#include "utils.h"
+#include "icmp.h"
+
+LRESULT CALLBACK NullWindowProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ switch( message ) {
+ case WM_COMMAND: {
+ PUDeletePopUp( hWnd );
+ break;
+ }
+
+ case WM_CONTEXTMENU:
+ PUDeletePopUp( hWnd );
+ break;
+ }
+
+ return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+void CALLBACK sttMainThreadCallback( ULONG_PTR dwParam )
+{
+ POPUPDATAEX* ppd = ( POPUPDATAEX* )dwParam;
+
+ if ( ServiceExists(MS_POPUP_ADDPOPUPEX) )
+ PUAddPopUpEx(ppd);
+
+ free( ppd );
+}
+
+void __stdcall ShowPopup( const char* line1, const char* line2, int flags )
+{
+ if(CallService(MS_SYSTEM_TERMINATED, 0, 0)) return;
+
+ if ( ServiceExists( MS_POPUP_ADDPOPUP )) {
+ POPUPDATAEX* ppd = ( POPUPDATAEX* )calloc( sizeof( POPUPDATAEX ), 1 );
+
+ ppd->lchContact = NULL;
+ ppd->lchIcon = (flags ? hIconResponding : hIconNotResponding);
+ strncpy( ppd->lpzContactName, line1,MAX_CONTACTNAME);
+ strncpy( ppd->lpzText, line2, MAX_SECONDLINE);
+
+ ppd->colorBack = GetSysColor( COLOR_BTNFACE );
+ ppd->colorText = GetSysColor( COLOR_WINDOWTEXT );
+ ppd->iSeconds = 10;
+
+ ppd->PluginWindowProc = NullWindowProc;
+ ppd->PluginData = NULL;
+
+ QueueUserAPC( sttMainThreadCallback , mainThread, ( ULONG )ppd );
+ }
+ else if(ServiceExists(MS_POPUP_ADDPOPUPCLASS)) {
+ POPUPDATACLASS d = {sizeof(d), "pingpopups"};
+ d.pwszTitle = (wchar_t *)line1;
+ d.pwszText = (wchar_t *)line2;
+ CallService(MS_POPUP_ADDPOPUPCLASS, 0, (LPARAM)&d);
+ } else {
+ MessageBox( NULL, line2, PLUG " Message", MB_OK | MB_ICONINFORMATION );
+ return;
+ }
+}
+
+// service functions
+
+// wParam is zero
+// lParam is address of PINGADDRESS structure where ping result is placed (i.e. modifies 'responding'
+// and 'round_trip_time')
+INT_PTR PluginPing(WPARAM wParam,LPARAM lParam)
+{
+ PINGADDRESS *pa = (PINGADDRESS *)lParam;
+
+ if(pa->port == -1) {
+ // ICMP echo
+ if(use_raw_ping) {
+ pa->round_trip_time = raw_ping(pa->pszName, options.ping_timeout * 1000);
+ pa->responding = (pa->round_trip_time != -1);
+ } else {
+
+ ICMP_ECHO_REPLY result;
+ pa->responding = ICMP::get_instance()->ping(pa->pszName, result);
+ if(pa->responding)
+ pa->round_trip_time = (short)result.RoundTripTime;
+ else
+ pa->round_trip_time = -1;
+ }
+ } else if(hNetlibUser) {
+ // TCP connect
+
+ clock_t start_tcp = clock();
+
+ //GetLocalTime(&systime);
+ NETLIBOPENCONNECTION conn = {0};
+ conn.cbSize = sizeof(NETLIBOPENCONNECTION);
+ conn.szHost = pa->pszName;
+ conn.wPort = pa->port;
+ conn.timeout = options.ping_timeout;
+
+ HANDLE s = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)hNetlibUser, (LPARAM)&conn);
+
+ clock_t end_tcp = clock();
+
+ if(s) {
+ LINGER l;
+ char buf[1024];
+ SOCKET socket = (SOCKET)CallService(MS_NETLIB_GETSOCKET, (WPARAM)s, (LPARAM)NLOCF_HTTP);
+ l.l_onoff = 1;
+ l.l_linger = 0;
+ setsockopt(socket, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(l));
+
+ Netlib_Send(s, "OUT\r\n\r\n", 7, 0); //MSG_RAW);
+
+ //Sleep(ICMP::get_instance()->get_timeout());
+ Sleep(options.ping_timeout * 1000);
+ unsigned long bytes_remaining;
+ ioctlsocket(socket, FIONBIO, &bytes_remaining);
+
+ if(bytes_remaining > 0) {
+ int retval, rx = 0;
+ while((retval = Netlib_Recv(s, buf, 1024, 0)) != SOCKET_ERROR && (retval > 0) && rx < 2048) {
+ rx += retval; // recv at most 2kb before closing connection
+ }
+ }
+ closesocket(socket);
+ pa->responding = true;
+ pa->round_trip_time = (int)(((end_tcp - start_tcp) / (double)CLOCKS_PER_SEC) * 1000);
+
+ Netlib_CloseHandle(s);
+ } else {
+ pa->responding = false;
+ pa->round_trip_time = -1;
+ }
+
+ }
+ return 0;
+}
+
+void Lock(CRITICAL_SECTION *cs, char *lab) {
+// if(logging) {
+// std::ostringstream oss1;
+// oss1 << "Locking cs: " << cs << ", " << lab;
+// CallService(PROTO "/Log", (WPARAM)oss1.str().c_str(), 0);
+// }
+ EnterCriticalSection(cs);
+// if(logging) {
+// std::ostringstream oss2;
+// oss2 << "Locked cs: " << cs;
+// CallService(PROTO "/Log", (WPARAM)oss2.str().c_str(), 0);
+// }
+}
+
+void Unlock(CRITICAL_SECTION *cs) {
+// if(logging) {
+// std::ostringstream oss1;
+// oss1 << "Unlocking cs: " << cs;
+// CallService(PROTO "/Log", (WPARAM)oss1.str().c_str(), 0);
+// }
+ LeaveCriticalSection(cs);
+}
+
+INT_PTR PingDisableAll(WPARAM wParam, LPARAM lParam) {
+ PINGLIST pl;
+ CallService(PLUG "/GetPingList", 0, (LPARAM)&pl);
+ for(PINGLIST::Iterator i = pl.start(); i.has_val(); i.next()) {
+ i.val().status = PS_DISABLED;
+ i.val().miss_count = 0;
+ }
+ CallService(PLUG "/SetPingList", (WPARAM)&pl, 0);
+ return 0;
+}
+
+INT_PTR PingEnableAll(WPARAM wParam, LPARAM lParam) {
+ PINGLIST pl;
+ CallService(PLUG "/GetPingList", 0, (LPARAM)&pl);
+ for(PINGLIST::Iterator i = pl.start(); i.has_val(); i.next()) {
+ if(i.val().status == PS_DISABLED) {
+ i.val().status = PS_NOTRESPONDING;
+ }
+ }
+ CallService(PLUG "/SetPingList", (WPARAM)&pl, 0);
+ return 0;
+}
+
+
+INT_PTR ToggleEnabled(WPARAM wParam, LPARAM lParam) {
+ int retval = 0;
+ PINGLIST pl;
+ CallService(PLUG "/GetPingList", 0, (LPARAM)&pl);
+ for(PINGLIST::Iterator i = pl.start(); i.has_val(); i.next()) {
+ if(i.val().item_id == (DWORD)wParam) {
+
+ if(i.val().status == PS_DISABLED)
+ i.val().status = PS_NOTRESPONDING;
+ else {
+ i.val().status = PS_DISABLED;
+ i.val().miss_count = 0;
+ retval = 1;
+ }
+ }
+ }
+ CallService(PLUG "/SetPingList", (WPARAM)&pl, 0);
+ return 0;
+}
+
+INT_PTR EditContact(WPARAM wParam, LPARAM lParam) {
+ PINGLIST pl;
+ HWND hwndList = (HWND)CallService(MS_CLUI_GETHWND, 0, 0);
+
+ CallService(PLUG "/GetPingList", 0, (LPARAM)&pl);
+ for(PINGLIST::Iterator i = pl.start(); i.has_val(); i.next()) {
+ if(i.val().item_id == (DWORD)wParam) {
+
+ add_edit_addr = i.val();
+
+ if(DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG3), hwndList, DlgProcDestEdit) == IDOK) {
+
+ i.val() = add_edit_addr;
+ CallService(PLUG "/SetAndSavePingList", (WPARAM)&pl, 0);
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+
+INT_PTR DblClick(WPARAM wParam, LPARAM lParam) {
+ PINGLIST pl;
+ CallService(PLUG "/GetPingList", 0, (LPARAM)&pl);
+ for(PINGLIST::Iterator i = pl.start(); i.has_val(); i.next()) {
+ if(i.val().item_id == (DWORD)wParam) {
+ if(strlen(i.val().pszCommand)) {
+ ShellExecute(0, "open", i.val().pszCommand, i.val().pszParams, 0, SW_SHOW);
+ } else {
+ return CallService(PLUG "/ToggleEnabled", wParam, 0);
+ }
+ }
+ }
+ return 0;
+}
+
+
+void import_ping_address(int index, PINGADDRESS &pa) {
+ DBVARIANT dbv;
+ char buf[256];
+ mir_snprintf(buf, 256, "Address%d", index);
+ if(!DBGetContactSetting(0, "PingPlug", buf, &dbv)) {
+ strncpy(pa.pszName, dbv.pszVal, MAX_PINGADDRESS_STRING_LENGTH);
+ DBFreeVariant(&dbv);
+ } else
+ strcpy(pa.pszName, Translate("Unknown Address"));
+
+ mir_snprintf(buf, 256, "Label%d", index);
+ if(!DBGetContactSetting(0, "PingPlug", buf, &dbv)) {
+ strncpy(pa.pszLabel, dbv.pszVal, MAX_PINGADDRESS_STRING_LENGTH);
+ DBFreeVariant(&dbv);
+ } else
+ strcpy(pa.pszLabel, Translate("Unknown"));
+
+ mir_snprintf(buf, 256, "Port%d", index);
+ pa.port = (int)DBGetContactSettingDword(0, "PingPlug", buf, -1);
+
+ mir_snprintf(buf, 256, "Proto%d", index);
+ if(!DBGetContactSetting(0, "PingPlug", buf, &dbv)) {
+ strncpy(pa.pszProto, dbv.pszVal, MAX_PINGADDRESS_STRING_LENGTH);
+ DBFreeVariant(&dbv);
+ mir_snprintf(buf, 256, "Status%d", index);
+ pa.set_status = DBGetContactSettingWord(0, "PingPlug", buf, ID_STATUS_ONLINE);
+ mir_snprintf(buf, 256, "Status2%d", index);
+ pa.get_status = DBGetContactSettingWord(0, "PingPlug", buf, ID_STATUS_OFFLINE);
+ } else
+ pa.pszProto[0] = '\0';
+
+
+ pa.responding = false;
+ pa.round_trip_time = 0;
+ pa.miss_count = 0;
+ pa.index = index;
+ pa.pszCommand[0] = '\0';
+ pa.pszParams[0] = '\0';
+
+ pa.item_id = 0;
+ mir_snprintf(buf, 256, "Enabled%d", index);
+ if(DBGetContactSettingByte(0, "PingPlug", buf, 1) == 1)
+ pa.status = PS_NOTRESPONDING;
+ else
+ pa.status = PS_DISABLED;
+}
+
+// read in addresses from old pingplug
+void import_ping_addresses() {
+ int count = DBGetContactSettingDword(0, "PingPlug", "NumEntries", 0);
+ PINGADDRESS pa;
+
+ EnterCriticalSection(&list_cs);
+ list_items.clear();
+ for(int index = 0; index < count; index++) {
+ import_ping_address(index, pa);
+ list_items.add(pa);
+ }
+ write_ping_addresses();
+ LeaveCriticalSection(&list_cs);
+}
+
+HANDLE hIcoLibIconsChanged;
+
+HICON hIconResponding, hIconNotResponding, hIconTesting, hIconDisabled;
+
+int ReloadIcons(WPARAM wParam, LPARAM lParam) {
+ hIconResponding = Skin_GetIcon("ping_responding");
+ hIconNotResponding = Skin_GetIcon("ping_not_responding");
+ hIconTesting = Skin_GetIcon("ping_testing");
+ hIconDisabled = Skin_GetIcon("ping_disabled");
+
+ RefreshWindow(0, 0);
+ return 0;
+}
+
+void InitUtils() {
+ TCHAR file[MAX_PATH];
+ GetModuleFileName(hInst,file,MAX_PATH);
+ {
+ SKINICONDESC sid = {0};
+
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.ptszSection = LPGENT("Ping");
+ sid.flags = SIDF_ALL_TCHAR;
+
+ sid.pszDescription = LPGENT("Responding");
+ sid.pszName = "ping_responding";
+ sid.ptszDefaultFile = file;
+ sid.iDefaultIndex = 0;
+ sid.hDefaultIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_ICON_RESPONDING), IMAGE_ICON, 16, 16, 0);
+ Skin_AddIcon(&sid);
+
+ sid.pszDescription = LPGENT("Not Responding");
+ sid.pszName = "ping_not_responding";
+ sid.ptszDefaultFile = file;
+ sid.iDefaultIndex = 1;
+ sid.hDefaultIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_ICON_NOTRESPONDING), IMAGE_ICON, 16, 16, 0);//LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS );
+ Skin_AddIcon(&sid);
+
+ sid.pszDescription = LPGENT("Testing");
+ sid.pszName = "ping_testing";
+ sid.ptszDefaultFile = file;
+ sid.iDefaultIndex = 2;
+ sid.hDefaultIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_ICON_TESTING), IMAGE_ICON, 16, 16, 0);//LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS );
+ Skin_AddIcon(&sid);
+
+ sid.pszDescription = LPGENT("Disabled");
+ sid.pszName = "ping_disabled";
+ sid.ptszDefaultFile = file;
+ sid.iDefaultIndex = 3;
+ sid.hDefaultIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_ICON_DISABLED), IMAGE_ICON, 16, 16, 0);//LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS );
+ Skin_AddIcon(&sid);
+
+ hIconResponding = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"ping_responding");
+ hIconNotResponding = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"ping_not_responding");
+ hIconTesting = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"ping_testing");
+ hIconDisabled = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"ping_disabled");
+
+ hIcoLibIconsChanged = HookEvent(ME_SKIN2_ICONSCHANGED, ReloadIcons);
+ }
+
+ if(ServiceExists(MS_POPUP_REGISTERCLASS)) {
+ POPUPCLASS test = {0};
+ test.cbSize = sizeof(test);
+ test.flags = PCF_TCHAR;
+ test.hIcon = hIconResponding;
+ test.iSeconds = -1;
+ test.ptszDescription = TranslateT("Ping");
+ test.pszName = "pingpopups";
+ test.PluginWindowProc = NullWindowProc;
+ CallService(MS_POPUP_REGISTERCLASS, 0, (WPARAM)&test);
+ }
+} \ No newline at end of file
diff --git a/plugins/Ping/utils.h b/plugins/Ping/utils.h
new file mode 100644
index 0000000000..0d27745908
--- /dev/null
+++ b/plugins/Ping/utils.h
@@ -0,0 +1,35 @@
+#ifndef _PING_UTILS
+#define _PING_UTILS
+
+#pragma warning( disable : 4786 )
+
+#include "pingthread.h" // for mainthread, for popup
+//#include "icmp.h"
+#include "rawping.h"
+#include "icmp.h"
+#include "options.h"
+
+void __stdcall ShowPopup( const char* line1, const char* line2, int flags );
+
+INT_PTR PluginPing(WPARAM wParam,LPARAM lParam);
+
+void Lock(CRITICAL_SECTION *cs, char *lab);
+void Unlock(CRITICAL_SECTION *cs);
+
+INT_PTR PingDisableAll(WPARAM wParam, LPARAM lParam);
+INT_PTR PingEnableAll(WPARAM wParam, LPARAM lParam);
+
+INT_PTR ToggleEnabled(WPARAM wParam, LPARAM lParam);
+
+INT_PTR DblClick(WPARAM wParam, LPARAM lParam);
+
+INT_PTR EditContact(WPARAM wParam, LPARAM lParam);
+// read in addresses from old pingplug
+void import_ping_addresses();
+
+// use icolib if possible
+void InitUtils();
+extern HICON hIconResponding, hIconNotResponding, hIconTesting, hIconDisabled;
+
+
+#endif
diff --git a/plugins/Ping/yellow.ico b/plugins/Ping/yellow.ico
new file mode 100644
index 0000000000..94f62a201d
--- /dev/null
+++ b/plugins/Ping/yellow.ico
Binary files differ