New Downloader
authorMaarten Bosma <maarten@bosma.de>
Fri, 15 Dec 2006 16:11:59 +0000 (16:11 +0000)
committerMaarten Bosma <maarten@bosma.de>
Fri, 15 Dec 2006 16:11:59 +0000 (16:11 +0000)
- Description field is not done yet.
- Download.c is taken from getfirefox.

svn path=/trunk/; revision=25168

25 files changed:
reactos/base/applications/applications.rbuild
reactos/base/applications/downloader/apps.xml [new file with mode: 0644]
reactos/base/applications/downloader/download.c [new file with mode: 0644]
reactos/base/applications/downloader/downloader.rbuild [new file with mode: 0644]
reactos/base/applications/downloader/downloader.rc [new file with mode: 0644]
reactos/base/applications/downloader/main.c [new file with mode: 0644]
reactos/base/applications/downloader/resources.h [new file with mode: 0644]
reactos/base/applications/downloader/resources/0.bmp [new file with mode: 0644]
reactos/base/applications/downloader/resources/1.bmp [new file with mode: 0644]
reactos/base/applications/downloader/resources/2.bmp [new file with mode: 0644]
reactos/base/applications/downloader/resources/3.bmp [new file with mode: 0644]
reactos/base/applications/downloader/resources/4.bmp [new file with mode: 0644]
reactos/base/applications/downloader/resources/5.bmp [new file with mode: 0644]
reactos/base/applications/downloader/resources/6.bmp [new file with mode: 0644]
reactos/base/applications/downloader/resources/7.bmp [new file with mode: 0644]
reactos/base/applications/downloader/resources/8.bmp [new file with mode: 0644]
reactos/base/applications/downloader/resources/download.bmp [new file with mode: 0644]
reactos/base/applications/downloader/resources/en.rc [new file with mode: 0644]
reactos/base/applications/downloader/resources/generic.rc [new file with mode: 0644]
reactos/base/applications/downloader/resources/help.bmp [new file with mode: 0644]
reactos/base/applications/downloader/resources/logo.bmp [new file with mode: 0644]
reactos/base/applications/downloader/resources/main.ico [new file with mode: 0644]
reactos/base/applications/downloader/resources/update.bmp [new file with mode: 0644]
reactos/base/applications/downloader/structures.h [new file with mode: 0644]
reactos/base/applications/downloader/xml.c [new file with mode: 0644]

index 661b5dd..2dcb549 100644 (file)
@@ -16,6 +16,9 @@
 <directory name="devmgr">
        <xi:include href="devmgr/devmgr.rbuild" />
 </directory>
+<directory name="downloader">
+       <xi:include href="downloader/downloader.rbuild" />
+</directory>
 <directory name="games">
        <xi:include href="games/games.rbuild" />
 </directory>
diff --git a/reactos/base/applications/downloader/apps.xml b/reactos/base/applications/downloader/apps.xml
new file mode 100644 (file)
index 0000000..72bf5c1
--- /dev/null
@@ -0,0 +1,24 @@
+<tree Version="1"> <!-- Application version this tree is made for -->\r
+       <category name="Internet &amp; Network" icon="1">\r
+               <category name="Browsers">\r
+                       <application name="Firefox">\r
+                               <description>The most popular free webbrowser out there.</description>\r
+                               <location>http://links.reactos.org/getfirefox</location>\r
+                       </application>\r
+               </category>\r
+       </category>\r
+       <category name="Office" icon="2">\r
+       </category>\r
+       <category name="Graphics" icon="3">\r
+       </category>\r
+       <category name="Multimedia" icon="4">\r
+       </category>\r
+       <category name="Development" icon="5">\r
+       </category>\r
+       <category name="Games &amp; Fun" icon="6">\r
+       </category>\r
+       <category name="Tools" icon="7">\r
+       </category>\r
+       <category name="Others" icon="8">\r
+       </category>\r
+</tree>
\ No newline at end of file
diff --git a/reactos/base/applications/downloader/download.c b/reactos/base/applications/downloader/download.c
new file mode 100644 (file)
index 0000000..d2f0f68
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * PROJECT:     ReactOS Downloader (was GetFirefox)
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        base/applications/downloader/download.c
+ * PURPOSE:     Displaying a download dialog
+ * COPYRIGHT:   Copyright 2001 John R. Sheets (for CodeWeavers)
+ *              Copyright 2004 Mike McCormack (for CodeWeavers)
+ *              Copyright 2005 Ge van Geldorp (gvg@reactos.org)
+ */
+/*
+ * Based on Wine dlls/shdocvw/shdocvw_main.c
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define COBJMACROS
+#define WIN32_NO_STATUS
+#include <windows.h>
+#include <commctrl.h>
+#include <shlobj.h>
+#include <shlwapi.h>
+#include <urlmon.h>
+
+#include "resources.h"
+#include "structures.h"
+
+#define NDEBUG
+#include <debug.h>
+
+extern struct Application* SelectedApplication;
+
+typedef struct _IBindStatusCallbackImpl
+  {
+    const IBindStatusCallbackVtbl *vtbl;
+    LONG ref;
+    HWND hDialog;
+    BOOL *pbCancelled;
+  } IBindStatusCallbackImpl;
+
+static HRESULT WINAPI
+dlQueryInterface(IBindStatusCallback* This, REFIID riid, void** ppvObject)
+{
+  if (NULL == ppvObject)
+    {
+      return E_POINTER;
+    }
+    
+  if (IsEqualIID(riid, &IID_IUnknown) ||
+      IsEqualIID(riid, &IID_IBindStatusCallback))
+    {
+      IBindStatusCallback_AddRef( This );
+      *ppvObject = This;
+      return S_OK;
+    }
+
+  return E_NOINTERFACE;
+}
+
+static ULONG WINAPI
+dlAddRef(IBindStatusCallback* iface)
+{
+  IBindStatusCallbackImpl *This = (IBindStatusCallbackImpl *) iface;
+    
+  return InterlockedIncrement(&This->ref);
+}
+
+static ULONG WINAPI
+dlRelease(IBindStatusCallback* iface)
+{
+  IBindStatusCallbackImpl *This = (IBindStatusCallbackImpl *) iface;
+  DWORD ref = InterlockedDecrement(&This->ref);
+    
+  if( !ref )
+    {
+      DestroyWindow( This->hDialog );
+      HeapFree(GetProcessHeap(), 0, This);
+    }
+    
+  return ref;
+}
+
+static HRESULT WINAPI
+dlOnStartBinding(IBindStatusCallback* iface, DWORD dwReserved, IBinding* pib)
+{
+  DPRINT1("OnStartBinding not implemented\n");
+
+  return S_OK;
+}
+
+static HRESULT WINAPI
+dlGetPriority(IBindStatusCallback* iface, LONG* pnPriority)
+{
+  DPRINT1("GetPriority not implemented\n");
+
+  return S_OK;
+}
+
+static HRESULT WINAPI
+dlOnLowResource( IBindStatusCallback* iface, DWORD reserved)
+{
+  DPRINT1("OnLowResource not implemented\n");
+
+  return S_OK;
+}
+
+static HRESULT WINAPI
+dlOnProgress(IBindStatusCallback* iface, ULONG ulProgress,
+             ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
+{
+  IBindStatusCallbackImpl *This = (IBindStatusCallbackImpl *) iface;
+  HWND Item;
+  LONG r;
+  WCHAR OldText[100];
+
+  Item = GetDlgItem(This->hDialog, IDC_PROGRESS);
+  if (NULL != Item && 0 != ulProgressMax)
+    {
+      SendMessageW(Item, PBM_SETPOS, (ulProgress * 100) / ulProgressMax, 0);
+    }
+
+  Item = GetDlgItem(This->hDialog, IDC_STATUS);
+  if (NULL != Item && NULL != szStatusText)
+    {
+      SendMessageW(Item, WM_GETTEXT, sizeof(OldText) / sizeof(OldText[0]),
+                   (LPARAM) OldText);
+      if (sizeof(OldText) / sizeof(OldText[0]) - 1 <= wcslen(OldText) ||
+          0 != wcscmp(OldText, szStatusText))
+        {
+          SendMessageW(Item, WM_SETTEXT, 0, (LPARAM) szStatusText);
+        }
+    }
+
+  SetLastError(0);
+  r = GetWindowLongPtrW(This->hDialog, GWLP_USERDATA);
+  if (0 != r || 0 != GetLastError())
+    {
+      *This->pbCancelled = TRUE;
+      DPRINT("Cancelled\n");
+      return E_ABORT;
+    }
+
+  return S_OK;
+}
+
+static HRESULT WINAPI
+dlOnStopBinding(IBindStatusCallback* iface, HRESULT hresult, LPCWSTR szError)
+{
+  DPRINT1("OnStopBinding not implemented\n");
+
+  return S_OK;
+}
+
+static HRESULT WINAPI
+dlGetBindInfo(IBindStatusCallback* iface, DWORD* grfBINDF, BINDINFO* pbindinfo)
+{
+  DPRINT1("GetBindInfo not implemented\n");
+
+  return S_OK;
+}
+
+static HRESULT WINAPI
+dlOnDataAvailable(IBindStatusCallback* iface, DWORD grfBSCF,
+                  DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
+{
+  DPRINT1("OnDataAvailable implemented\n");
+
+  return S_OK;
+}
+
+static HRESULT WINAPI
+dlOnObjectAvailable(IBindStatusCallback* iface, REFIID riid, IUnknown* punk)
+{
+  DPRINT1("OnObjectAvailable implemented\n");
+
+  return S_OK;
+}
+
+static const IBindStatusCallbackVtbl dlVtbl =
+{
+    dlQueryInterface,
+    dlAddRef,
+    dlRelease,
+    dlOnStartBinding,
+    dlGetPriority,
+    dlOnLowResource,
+    dlOnProgress,
+    dlOnStopBinding,
+    dlGetBindInfo,
+    dlOnDataAvailable,
+    dlOnObjectAvailable
+};
+
+static IBindStatusCallback*
+CreateDl(HWND Dlg, BOOL *pbCancelled)
+{
+  IBindStatusCallbackImpl *This;
+
+  This = HeapAlloc(GetProcessHeap(), 0, sizeof(IBindStatusCallbackImpl));
+  This->vtbl = &dlVtbl;
+  This->ref = 1;
+  This->hDialog = Dlg;
+  This->pbCancelled = pbCancelled;
+
+  return (IBindStatusCallback*) This;
+}
+
+static DWORD WINAPI
+ThreadFunc(LPVOID Context)
+{
+  //static const WCHAR szUrl[] = DownloadUrl;
+  IBindStatusCallback *dl;
+  WCHAR path[MAX_PATH];
+  LPWSTR p;
+  STARTUPINFOW si;
+  PROCESS_INFORMATION pi;
+  HWND Dlg = (HWND) Context;
+  DWORD r;
+  BOOL bCancelled = FALSE;
+  BOOL bTempfile = FALSE;
+
+  /* built the path for the download */
+  p = wcsrchr(SelectedApplication->Location, L'/');
+  if (NULL == p)
+    {
+      goto end;
+    }
+  if (! GetTempPathW(MAX_PATH, path))
+    {
+      goto end;
+    }
+  wcscat(path, p + 1);
+
+  /* download it */
+  bTempfile = TRUE;
+  dl = CreateDl(Context, &bCancelled);
+  r = URLDownloadToFileW(NULL, SelectedApplication->Location, path, 0, dl);
+  if (NULL != dl)
+    {
+      IBindStatusCallback_Release(dl);
+    }
+  if (S_OK != r || bCancelled )
+    {
+      goto end;
+    }
+  ShowWindow(Dlg, SW_HIDE);
+
+  /* run it */
+  memset(&si, 0, sizeof(si));
+  si.cb = sizeof(si);
+  r = CreateProcessW(path, NULL, NULL, NULL, 0, 0, NULL, NULL, &si, &pi);
+  if (0 == r)
+    {
+      goto end;
+    }
+  CloseHandle(pi.hThread);
+  WaitForSingleObject(pi.hProcess, INFINITE);
+  CloseHandle(pi.hProcess);
+
+end:
+  if (bTempfile)
+    {
+      DeleteFileW(path);
+    }
+  EndDialog(Dlg, 0);
+  return 0;
+}
+
+INT_PTR CALLBACK
+DownloadProc(HWND Dlg, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+  HANDLE Thread;
+  DWORD ThreadId;
+  HWND Item;
+
+  switch (Msg)
+    {
+    case WM_INITDIALOG:/*
+      Icon = LoadIconW((HINSTANCE) GetWindowLongPtr(Dlg, GWLP_HINSTANCE),
+                       MAKEINTRESOURCEW(IDI_ICON_MAIN));
+      if (NULL != Icon)
+        {
+          SendMessageW(Dlg, WM_SETICON, ICON_BIG, (LPARAM) Icon);
+          SendMessageW(Dlg, WM_SETICON, ICON_SMALL, (LPARAM) Icon);
+        }*/
+      SetWindowLongPtrW(Dlg, GWLP_USERDATA, 0);
+      Item = GetDlgItem(Dlg, IDC_PROGRESS);
+      if (NULL != Item)
+        {
+          SendMessageW(Item, PBM_SETRANGE, 0, MAKELPARAM(0,100));
+          SendMessageW(Item, PBM_SETPOS, 0, 0);
+        }/*
+      Item = GetDlgItem(Dlg, IDC_REMOVE);
+      if (NULL != Item)
+        {
+          if (GetShortcutName(ShortcutName) &&
+              INVALID_FILE_ATTRIBUTES != GetFileAttributesW(ShortcutName))
+            {
+              SendMessageW(Item, BM_SETCHECK, BST_CHECKED, 0);
+            }
+          else
+            {
+              SendMessageW(Item, BM_SETCHECK, BST_UNCHECKED, 0);
+              ShowWindow(Item, SW_HIDE);
+            }
+        }*/
+      Thread = CreateThread(NULL, 0, ThreadFunc, Dlg, 0, &ThreadId);
+      if (NULL == Thread)
+        {
+          return FALSE;
+        }
+      CloseHandle(Thread);
+      return TRUE;
+
+    case WM_COMMAND:
+      if (wParam == IDCANCEL)
+        {
+          SetWindowLongPtrW(Dlg, GWLP_USERDATA, 1);
+          PostMessage(Dlg, WM_CLOSE, 0, 0);
+        }
+      return FALSE;
+
+    case WM_CLOSE:
+        EndDialog(Dlg, 0);
+        return TRUE;
+
+       default:
+      return FALSE;
+    }
+}
diff --git a/reactos/base/applications/downloader/downloader.rbuild b/reactos/base/applications/downloader/downloader.rbuild
new file mode 100644 (file)
index 0000000..a503967
--- /dev/null
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>\r
+<!DOCTYPE project SYSTEM "tools/rbuild/project.dtd">\r
+<module name="downloader" type="win32gui" installbase="system32" installname="downloader.exe" allowwarnings="true" stdlib="host">\r
+       <include base="downloader">.</include>\r
+       <include base="expat">.</include>\r
+\r
+       <define name="UNICODE" />\r
+       <define name="_UNICODE" />\r
+       <define name="__USE_W32API" />\r
+       <define name="WINVER">0x0501</define>\r
+       <define name="_WIN32_IE>0x0600</define>\r
+\r
+       <library>kernel32</library>\r
+       <library>ntdll</library>\r
+       <library>user32</library>\r
+       <library>gdi32</library>\r
+       <library>shell32</library>\r
+       <library>comctl32</library>\r
+       <library>msimg32</library>\r
+       <library>shlwapi</library>\r
+       <library>urlmon</library>\r
+       <library>uuid</library>\r
+       <library>expat</library>\r
+\r
+       <file>main.c</file>\r
+       <file>xml.c</file>\r
+       <file>download.c</file>\r
+       <file>downloader.rc</file>\r
+</module>\r
diff --git a/reactos/base/applications/downloader/downloader.rc b/reactos/base/applications/downloader/downloader.rc
new file mode 100644 (file)
index 0000000..4c894b6
--- /dev/null
@@ -0,0 +1,15 @@
+#include <windows.h>\r
+#include "resources.h"\r
+\r
+#define REACTOS_STR_FILE_DESCRIPTION   "Download !\0"\r
+#define REACTOS_STR_INTERNAL_NAME      "downloader\0"\r
+#define REACTOS_STR_ORIGINAL_FILENAME  "downloader.exe\0"\r
+\r
+#include <reactos/version.rc>\r
+\r
+#include "resources/generic.rc"\r
+#include "resources/en.rc"\r
+\r
+\r
+\r
+\r
diff --git a/reactos/base/applications/downloader/main.c b/reactos/base/applications/downloader/main.c
new file mode 100644 (file)
index 0000000..7e72848
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * PROJECT:         ReactOS Downloader
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            base/applications/downloader/xml.c
+ * PURPOSE:         Main program
+ * PROGRAMMERS:     Maarten Bosma
+ */
+
+#include <windows.h>
+#include <commctrl.h>
+#include <richedit.h>
+#include <stdio.h>
+#include "resources.h"
+#include "structures.h"
+
+HWND hCategories, hApps, hDescription, hBtnDownload, hBtnUpdate, hBtnHelp;
+HBITMAP hLogo;
+
+struct Category Root;
+struct Application* SelectedApplication;
+
+INT_PTR CALLBACK DownloadProc (HWND, UINT, WPARAM, LPARAM);
+BOOL ProcessXML (const char* filename, struct Category* Root);
+void FreeTree (struct Category* Node);
+
+
+void ShowMessage (WCHAR* title, WCHAR* message)
+{
+       SETTEXTEX Text = {ST_SELECTION, 1200};
+
+       SendMessage(hDescription, WM_SETTEXT, 0, 0);
+       SendMessage(hDescription, EM_SETTEXTEX, (WPARAM)&Text, (LPARAM)title);
+       SendMessage(hDescription, EM_SETTEXTEX, (WPARAM)&Text, (LPARAM)L"\n----------------------------------------\n");
+       SendMessage(hDescription, EM_SETTEXTEX, (WPARAM)&Text, (LPARAM)message);
+}
+
+void AddItems (HWND hwnd, struct Category* Category, struct Category* Parent)
+{ 
+       TV_INSERTSTRUCT Insert; 
+
+       Insert.item.lParam = (UINT)Category;
+       Insert.item.mask = TVIF_TEXT|TVIF_PARAM;
+       Insert.item.pszText = Category->Name; //that is okay
+       Insert.item.cchTextMax = lstrlen(Category->Name); 
+       Insert.hInsertAfter = TVI_LAST;
+       Insert.hParent = Category->Parent ? Category->Parent->TreeviewItem : TVI_ROOT;
+
+       if(Category->Icon)
+       {
+               Insert.item.iImage = Category->Icon;
+               Insert.item.iSelectedImage = Category->Icon;
+               Insert.item.mask |= TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+       }
+
+       Category->TreeviewItem = (HTREEITEM)SendMessage(hwnd, TVM_INSERTITEM, 0, (LPARAM)&Insert);
+
+       if(Category->Next)
+               AddItems (hwnd,Category->Next,Parent);
+
+       if(Category->Children)
+               AddItems (hwnd,Category->Children,Category);
+}
+
+void DisplayApps (HWND hwnd, struct Category* Category)
+{
+       struct Application* CurrentApplication = Category->Apps;
+
+       TreeView_DeleteItem(hwnd, TVI_ROOT);
+
+       TV_INSERTSTRUCT Insert;
+       Insert.item.mask = TVIF_TEXT|TVIF_PARAM;
+       Insert.hInsertAfter = TVI_LAST;
+       Insert.hParent = TVI_ROOT;
+
+       while(CurrentApplication)
+       {
+               Insert.item.lParam = (UINT)CurrentApplication;
+               Insert.item.pszText = CurrentApplication->Name;
+               Insert.item.cchTextMax = lstrlen(CurrentApplication->Name); 
+               SendMessage(hwnd, TVM_INSERTITEM, 0, (LPARAM)&Insert);
+               CurrentApplication = CurrentApplication->Next;
+       }
+} 
+
+void SetupControls (HWND hwnd)
+{
+       HINSTANCE hInstance = GetModuleHandle(NULL);
+
+       // Set up the controls
+       hCategories = CreateWindowEx(0, WC_TREEVIEW, L"Categories", WS_CHILD|WS_VISIBLE|WS_BORDER|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_SHOWSELALWAYS, 
+                                                       0, 0, 0, 0, hwnd, NULL, hInstance, NULL);
+
+       hApps = CreateWindowEx(0, WC_TREEVIEW, L"Applications", WS_CHILD|WS_VISIBLE|WS_BORDER|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_SHOWSELALWAYS, 
+                                                       0, 0, 0, 0, hwnd, NULL, hInstance, NULL);
+
+       hDescription = CreateWindowEx(WS_EX_WINDOWEDGE, RICHEDIT_CLASS, L"", WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_READONLY, //|ES_AUTOHSCROLL
+                                                       0, 0, 0, 0, hwnd, NULL, hInstance, NULL);
+
+       hLogo = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_LOGO));
+
+       hBtnHelp = CreateWindow (L"Button", L"", WS_CHILD|WS_VISIBLE|BS_BITMAP, 550, 10, 40, 40, hwnd, 0, hInstance, NULL);
+       hBtnUpdate = CreateWindow (L"Button", L"", WS_CHILD|WS_VISIBLE|BS_BITMAP, 500, 10, 40, 40, hwnd, 0, hInstance, NULL);
+       hBtnDownload = CreateWindow (L"Button", L"", WS_CHILD|WS_VISIBLE|BS_BITMAP, 330, 505, 140, 33, hwnd, 0, hInstance, NULL);
+
+       SendMessage (hBtnHelp, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)(HANDLE)LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_HELP)));
+       SendMessage (hBtnUpdate, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP,(LPARAM)(HANDLE)LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_UPDATE)));
+       SendMessage (hBtnDownload, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP,(LPARAM)(HANDLE)LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_DOWNLOAD)));
+
+       // Create Tree Icons
+       HIMAGELIST hImageList = ImageList_Create(16, 16, ILC_COLORDDB, 1, 1);
+       SendMessage(hCategories, TVM_SETIMAGELIST, TVSIL_NORMAL, (LPARAM)(HIMAGELIST)hImageList);
+       SendMessage(hApps, TVM_SETIMAGELIST, TVSIL_NORMAL, (LPARAM)(HIMAGELIST)hImageList);
+
+       ImageList_Add(hImageList, LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_0)), NULL); 
+       ImageList_Add(hImageList, LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_1)), NULL); 
+       ImageList_Add(hImageList, LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_2)), NULL); 
+       ImageList_Add(hImageList, LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_3)), NULL); 
+       ImageList_Add(hImageList, LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_4)), NULL); 
+       ImageList_Add(hImageList, LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_5)), NULL); 
+       ImageList_Add(hImageList, LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_6)), NULL); 
+       ImageList_Add(hImageList, LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_7)), NULL); 
+       ImageList_Add(hImageList, LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TREEVIEW_ICON_8)), NULL); 
+
+       // Fill the TreeViews
+       ProcessXML ("C:\\reactos\\base\\applications\\downloader\\apps.xml", &Root);
+       AddItems (hCategories, Root.Children, NULL);
+}
+
+static void ResizeControl (HWND hwnd, int x1, int y1, int x2, int y2)
+{
+       // Make resizing a little easier
+       MoveWindow(hwnd, x1, y1, x2-x1, y2-y1, TRUE);
+}
+
+static void DrawBitmap (HWND hwnd, int x, int y, HBITMAP hBmp)
+{
+       BITMAP bm;
+       PAINTSTRUCT ps;
+
+       HDC hdc = BeginPaint(hwnd, &ps);
+       HDC hdcMem = CreateCompatibleDC(hdc);
+
+       SelectObject(hdcMem, hBmp);
+       GetObject(hBmp, sizeof(bm), &bm);
+       
+       //BitBlt(hdc, x, y, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
+       TransparentBlt(hdc, x, y, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, 0xFFFFFF);
+
+       DeleteDC(hdcMem);
+       EndPaint(hwnd, &ps);
+}
+
+LRESULT CALLBACK WndProc (HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
+{
+       switch (Message)
+       {
+               case WM_CREATE:
+               {
+                       SetupControls(hwnd);
+                       ShowMessage(L"ReactOS Downloader", L"Welcome to ReactOS's Downloader\nPlease choose a category on the right. This is version 0.5.");
+               } 
+               break;
+
+               case WM_PAINT:
+               {
+                       DrawBitmap(hwnd, 10, 12, hLogo);
+               }
+               break;
+
+               case WM_COMMAND:
+               {
+                       if(HIWORD(wParam) == BN_CLICKED)
+                       {
+                               if (lParam == (LPARAM)hBtnDownload)
+                               {
+                                       DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCEW(IDD_DOWNLOAD), 0, DownloadProc);
+                               }
+                               else if (lParam == (LPARAM)hBtnUpdate)
+                               {
+                                       ShowMessage (L"Update", L"Feature not implemented yet.");
+                               }
+                               else if (lParam == (LPARAM)hBtnHelp)
+                               {
+                                       ShowMessage (L"Help", L"Choose a category on the right, then choose a application and click the download button.To update the application information click the button next to the help button.");
+                               }
+                       }
+               }
+               break;
+
+               case WM_NOTIFY:
+               {
+                       LPNMHDR data = (LPNMHDR)lParam;
+                       if(data->code == TVN_SELCHANGED)
+                       {
+                               if(data->hwndFrom == hCategories) 
+                               {
+                                       DisplayApps (hApps, (struct Category*) ((LPNMTREEVIEW)lParam)->itemNew.lParam);
+                               }
+                               else if(data->hwndFrom == hApps) 
+                               {
+                                       SelectedApplication = (struct Application*) ((LPNMTREEVIEW)lParam)->itemNew.lParam;
+                                       ShowMessage(SelectedApplication->Name, SelectedApplication->Description);
+                               }
+                       }
+               }
+               break;
+
+               case WM_SIZE:
+               {
+                       int Split_Hozizontal = (HIWORD(lParam)-(45+60))/2 + 60;
+                       int Split_Vertical = 200;
+
+                       ResizeControl(hCategories, 10, 60, Split_Vertical, HIWORD(lParam)-10);
+                       ResizeControl(hApps, Split_Vertical+5, 60, LOWORD(lParam)-10, Split_Hozizontal);
+                       ResizeControl(hDescription, Split_Vertical+5, Split_Hozizontal+5, LOWORD(lParam)-10, HIWORD(lParam)-50);
+
+                       MoveWindow(hBtnHelp, LOWORD(lParam)-50, 10, 40, 40, 0);
+                       MoveWindow(hBtnUpdate, LOWORD(lParam)-100, 10, 40, 40, 0);
+                       MoveWindow(hBtnDownload, (Split_Vertical+LOWORD(lParam))/2-70, HIWORD(lParam)-45, 140, 35, 0);
+               }
+               break;
+
+               case WM_DESTROY:
+               {
+                       DeleteObject(hLogo);
+                       FreeTree(Root.Children);
+                       PostQuitMessage(0);
+                       return 0;
+               }
+               break;
+       }
+
+       return DefWindowProc (hwnd, Message, wParam, lParam);
+}
+
+INT WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInst,
+                                       LPSTR lpCmdLine, INT nCmdShow)
+{
+       HWND hwnd;
+
+       LoadLibrary(L"riched20.dll");
+       InitCommonControls();
+
+       // Create the window
+       WNDCLASSEX WndClass = {0};
+       WndClass.cbSize                 = sizeof(WNDCLASSEX); 
+       WndClass.lpszClassName  = L"Downloader";
+       WndClass.style                  = CS_HREDRAW | CS_VREDRAW;
+       WndClass.lpfnWndProc    = WndProc;
+       WndClass.hInstance              = hInstance;
+       WndClass.hIcon                  = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAIN));
+       WndClass.hCursor                = LoadCursor(NULL, IDC_ARROW);
+       WndClass.hbrBackground  = (HBRUSH)CreateSolidBrush(RGB(235,233,237));
+
+       RegisterClassEx(&WndClass);
+
+       hwnd = CreateWindow(L"Downloader", 
+                                               L"Download ! - ReactOS Downloader",
+                                               WS_OVERLAPPEDWINDOW,
+                                               CW_USEDEFAULT,  
+                                               CW_USEDEFAULT,   
+                                               600, 550, 
+                                               NULL, NULL,
+                                               hInstance, 
+                                               NULL);
+
+       // Show it
+       ShowWindow(hwnd, SW_SHOW);
+       UpdateWindow(hwnd);
+
+       // Message Loop
+       MSG msg;
+       while(GetMessage(&msg,NULL,0,0))
+       {
+               TranslateMessage(&msg);
+               DispatchMessage(&msg);
+       }
+
+       return 0;
+}
diff --git a/reactos/base/applications/downloader/resources.h b/reactos/base/applications/downloader/resources.h
new file mode 100644 (file)
index 0000000..2a11fc1
--- /dev/null
@@ -0,0 +1,22 @@
+
+#define IDI_MAIN                       0x0
+#define IDB_UNDERLINE          0x100
+#define IDB_LOGO                       0x101
+#define IDB_HELP                       0x102
+#define IDB_UPDATE                     0x103
+#define IDB_DOWNLOAD           0x104
+#define IDB_TREEVIEW_ICON_0    0x900
+#define IDB_TREEVIEW_ICON_1    0x901
+#define IDB_TREEVIEW_ICON_2    0x902
+#define IDB_TREEVIEW_ICON_3    0x903
+#define IDB_TREEVIEW_ICON_4    0x904
+#define IDB_TREEVIEW_ICON_5    0x905
+#define IDB_TREEVIEW_ICON_6    0x906
+#define IDB_TREEVIEW_ICON_7    0x907
+#define IDB_TREEVIEW_ICON_8    0x908
+#define IDD_DOWNLOAD           0x100
+#define IDC_PROGRESS           0x1000
+#define IDC_STATUS                     0x1001
+#define IDC_REMOVE                     0x1002
+
+
diff --git a/reactos/base/applications/downloader/resources/0.bmp b/reactos/base/applications/downloader/resources/0.bmp
new file mode 100644 (file)
index 0000000..e31ccef
Binary files /dev/null and b/reactos/base/applications/downloader/resources/0.bmp differ
diff --git a/reactos/base/applications/downloader/resources/1.bmp b/reactos/base/applications/downloader/resources/1.bmp
new file mode 100644 (file)
index 0000000..b5d584b
Binary files /dev/null and b/reactos/base/applications/downloader/resources/1.bmp differ
diff --git a/reactos/base/applications/downloader/resources/2.bmp b/reactos/base/applications/downloader/resources/2.bmp
new file mode 100644 (file)
index 0000000..e59ab5e
Binary files /dev/null and b/reactos/base/applications/downloader/resources/2.bmp differ
diff --git a/reactos/base/applications/downloader/resources/3.bmp b/reactos/base/applications/downloader/resources/3.bmp
new file mode 100644 (file)
index 0000000..860744a
Binary files /dev/null and b/reactos/base/applications/downloader/resources/3.bmp differ
diff --git a/reactos/base/applications/downloader/resources/4.bmp b/reactos/base/applications/downloader/resources/4.bmp
new file mode 100644 (file)
index 0000000..5df366d
Binary files /dev/null and b/reactos/base/applications/downloader/resources/4.bmp differ
diff --git a/reactos/base/applications/downloader/resources/5.bmp b/reactos/base/applications/downloader/resources/5.bmp
new file mode 100644 (file)
index 0000000..fd5099e
Binary files /dev/null and b/reactos/base/applications/downloader/resources/5.bmp differ
diff --git a/reactos/base/applications/downloader/resources/6.bmp b/reactos/base/applications/downloader/resources/6.bmp
new file mode 100644 (file)
index 0000000..280fc7e
Binary files /dev/null and b/reactos/base/applications/downloader/resources/6.bmp differ
diff --git a/reactos/base/applications/downloader/resources/7.bmp b/reactos/base/applications/downloader/resources/7.bmp
new file mode 100644 (file)
index 0000000..1c8007b
Binary files /dev/null and b/reactos/base/applications/downloader/resources/7.bmp differ
diff --git a/reactos/base/applications/downloader/resources/8.bmp b/reactos/base/applications/downloader/resources/8.bmp
new file mode 100644 (file)
index 0000000..e300642
Binary files /dev/null and b/reactos/base/applications/downloader/resources/8.bmp differ
diff --git a/reactos/base/applications/downloader/resources/download.bmp b/reactos/base/applications/downloader/resources/download.bmp
new file mode 100644 (file)
index 0000000..09ff0a3
Binary files /dev/null and b/reactos/base/applications/downloader/resources/download.bmp differ
diff --git a/reactos/base/applications/downloader/resources/en.rc b/reactos/base/applications/downloader/resources/en.rc
new file mode 100644 (file)
index 0000000..83a92bb
--- /dev/null
@@ -0,0 +1,11 @@
+LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT\r
+\r
+IDD_DOWNLOAD DIALOG LOADONCALL MOVEABLE DISCARDABLE  0, 0, 220, 76\r
+STYLE DS_MODALFRAME | DS_CENTER | WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU\r
+CAPTION "Downloading Firefox"\r
+FONT 8, "MS Shell Dlg"\r
+{\r
+  CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER|PBS_SMOOTH,10,10,200,12\r
+  LTEXT "", IDC_STATUS, 10, 30, 200, 10, SS_CENTER\r
+  PUSHBUTTON "Cancel", IDCANCEL, 85, 58, 50, 15, WS_GROUP | WS_TABSTOP\r
+}\r
diff --git a/reactos/base/applications/downloader/resources/generic.rc b/reactos/base/applications/downloader/resources/generic.rc
new file mode 100644 (file)
index 0000000..f0600af
--- /dev/null
@@ -0,0 +1,17 @@
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL\r
+\r
+IDI_MAIN               ICON DISCARDABLE        "main.ico"\r
+IDB_UNDERLINE          BITMAP DISCARDABLE      "underline.bmp"\r
+IDB_LOGO               BITMAP DISCARDABLE      "logo.bmp"\r
+IDB_HELP               BITMAP DISCARDABLE      "help.bmp"\r
+IDB_UPDATE             BITMAP DISCARDABLE      "update.bmp"\r
+IDB_DOWNLOAD           BITMAP DISCARDABLE      "download.bmp"\r
+IDB_TREEVIEW_ICON_0    BITMAP DISCARDABLE      "0.bmp"\r
+IDB_TREEVIEW_ICON_1    BITMAP DISCARDABLE      "1.bmp"\r
+IDB_TREEVIEW_ICON_2    BITMAP DISCARDABLE      "2.bmp"\r
+IDB_TREEVIEW_ICON_3    BITMAP DISCARDABLE      "3.bmp"\r
+IDB_TREEVIEW_ICON_4    BITMAP DISCARDABLE      "4.bmp"\r
+IDB_TREEVIEW_ICON_5    BITMAP DISCARDABLE      "5.bmp"\r
+IDB_TREEVIEW_ICON_6    BITMAP DISCARDABLE      "6.bmp"\r
+IDB_TREEVIEW_ICON_7    BITMAP DISCARDABLE      "7.bmp"\r
+IDB_TREEVIEW_ICON_8    BITMAP DISCARDABLE      "8.bmp"\r
diff --git a/reactos/base/applications/downloader/resources/help.bmp b/reactos/base/applications/downloader/resources/help.bmp
new file mode 100644 (file)
index 0000000..59a5bd5
Binary files /dev/null and b/reactos/base/applications/downloader/resources/help.bmp differ
diff --git a/reactos/base/applications/downloader/resources/logo.bmp b/reactos/base/applications/downloader/resources/logo.bmp
new file mode 100644 (file)
index 0000000..4f10e49
Binary files /dev/null and b/reactos/base/applications/downloader/resources/logo.bmp differ
diff --git a/reactos/base/applications/downloader/resources/main.ico b/reactos/base/applications/downloader/resources/main.ico
new file mode 100644 (file)
index 0000000..86c43d7
Binary files /dev/null and b/reactos/base/applications/downloader/resources/main.ico differ
diff --git a/reactos/base/applications/downloader/resources/update.bmp b/reactos/base/applications/downloader/resources/update.bmp
new file mode 100644 (file)
index 0000000..d21aeec
Binary files /dev/null and b/reactos/base/applications/downloader/resources/update.bmp differ
diff --git a/reactos/base/applications/downloader/structures.h b/reactos/base/applications/downloader/structures.h
new file mode 100644 (file)
index 0000000..d0c9096
--- /dev/null
@@ -0,0 +1,23 @@
+
+struct Application
+{
+       WCHAR Name[0x100];
+       WCHAR Version[0x100];
+       WCHAR Maintainer[0x100];
+       WCHAR Licence[0x100];
+       WCHAR Description[0x400];
+       WCHAR Location[0x100];
+       struct Application* Next;
+};
+
+struct Category
+{
+       WCHAR Name[0x100];
+       //WCHAR Description[0x100];
+       int Icon;
+       HANDLE TreeviewItem;
+       struct Application* Apps;
+       struct Category* Next;
+       struct Category* Children;
+       struct Category* Parent;
+};
diff --git a/reactos/base/applications/downloader/xml.c b/reactos/base/applications/downloader/xml.c
new file mode 100644 (file)
index 0000000..15e3481
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * PROJECT:         ReactOS Downloader
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            base\applications\downloader\xml.c
+ * PURPOSE:         Parsing of application information xml files
+ * PROGRAMMERS:     Maarten Bosma
+ */
+
+#include <libs/expat/expat.h>
+#include <string.h>
+#include <stdio.h>
+#include <windows.h>
+#include "structures.h"
+
+BOOL TagOpen;
+struct Category* Current;
+struct Application* CurrentApplication;
+char CurrentTag [0x100];
+
+void tag_opened (void* usrdata, const char* tag, const char** arg)
+{
+       if(!strcmp(tag, "tree") && !CurrentApplication)
+       {
+               // check version
+       }
+
+       else if(!strcmp(tag, "category") && !CurrentApplication)
+       {
+               if (!Current)
+               {
+                       Current = malloc(sizeof(struct Category));
+                       memset(Current, 0, sizeof(struct Category));
+               }
+               else if (TagOpen)
+               {
+                       Current->Children = malloc(sizeof(struct Category));
+                       memset(Current->Children, 0, sizeof(struct Category));
+                       Current->Children->Parent = Current;
+                       Current = Current->Children;
+               }
+               else
+               {
+                       Current->Next = malloc(sizeof(struct Category));
+                       memset(Current->Next, 0, sizeof(struct Category));
+                       Current->Next->Parent = Current->Parent;
+                       Current = Current->Next;
+               }
+               TagOpen = TRUE;
+
+               int i;
+               for (i=0; arg[i]; i+=2) 
+               {
+                       if(!strcmp(arg[i], "name"))
+                       {
+                               MultiByteToWideChar(CP_ACP, 0, arg[i+1], -1, Current->Name, 0x100);
+                       }
+                       if(!strcmp(arg[i], "icon"))
+                       {
+                               Current->Icon = atoi(arg[i+1]);
+                       }
+               }
+       }
+
+       else if(!strcmp(tag, "application") && !CurrentApplication)
+       {
+               if(Current->Apps)
+               {
+                       CurrentApplication = Current->Apps;
+                       while(CurrentApplication->Next)
+                               CurrentApplication = CurrentApplication->Next;
+                       CurrentApplication->Next = malloc(sizeof(struct Application));
+                       memset(CurrentApplication->Next, 0, sizeof(struct Application));
+                       CurrentApplication = CurrentApplication->Next;
+               }
+               else
+               {
+                       Current->Apps = malloc(sizeof(struct Application));
+                       memset(Current->Apps, 0, sizeof(struct Application));
+                       CurrentApplication = Current->Apps;
+               }
+
+               int i;
+               for (i=0; arg[i]; i+=2) 
+               {
+                       if(!strcmp(arg[i], "name"))
+                       {
+                               MultiByteToWideChar(CP_ACP, 0, arg[i+1], -1, CurrentApplication->Name, 0x100);
+                       }
+               }
+       }
+       else if (CurrentApplication)
+       {
+               strncpy(CurrentTag, tag, 0x100);
+       }
+       else
+               MessageBox(0,L"Invaild XML File1",0,0);
+}
+
+
+void text (void* usrdata, const char* data, int len)
+{
+       if (!CurrentApplication)
+               return;
+
+       // FIXME: handle newlines e.g. in Description
+       if(!strcmp(CurrentTag, "maintainer"))
+       {
+               int currentlengt = lstrlen(CurrentApplication->Location);
+               MultiByteToWideChar(CP_ACP, 0, data, len, &CurrentApplication->Maintainer[currentlengt], 0x100-currentlengt);
+       }
+       else if(!strcmp(CurrentTag, "description"))
+       {
+               int currentlengt = lstrlen(CurrentApplication->Description);
+               MultiByteToWideChar(CP_ACP, 0, data, len, &CurrentApplication->Description[currentlengt], 0x400-currentlengt);
+       }
+       else if(!strcmp(CurrentTag, "location"))
+       {
+               int currentlengt = lstrlen(CurrentApplication->Location);
+               MultiByteToWideChar(CP_ACP, 0, data, len, &CurrentApplication->Location[currentlengt], 0x100-currentlengt);
+               MessageBox(0,CurrentApplication->Location,0,0);
+       }
+}
+
+void tag_closed (void* tree, const char* tag)
+{
+       CurrentTag[0] = 0;
+
+       if(!strcmp(tag, "category"))
+       {
+               if (TagOpen)
+               {
+                       TagOpen = FALSE;
+               }
+               else
+               {
+                       Current = Current->Parent;
+               }
+       }
+       else if(!strcmp(tag, "application"))
+       {
+               CurrentApplication = NULL;
+       }
+}
+
+BOOL ProcessXML (const char* filename, struct Category* Root) 
+{
+       int done = 0;
+       char buffer[255];
+
+       if(Current)
+               return FALSE;
+
+       Current = Root;
+       TagOpen = TRUE;
+
+       FILE* file = fopen(filename, "r");
+       if(!file) 
+       {
+               MessageBox(0,L"Could not find the xml file !",0,0);
+               return FALSE;
+       }
+
+       XML_Parser parser = XML_ParserCreate(NULL);
+       XML_SetElementHandler(parser, tag_opened, tag_closed);
+       XML_SetCharacterDataHandler(parser, text);
+
+       while (!done)
+       {
+               size_t len = fread (buffer, 1, sizeof(buffer), file);
+               done = len < sizeof(buffer);
+
+               buffer[len] = 0;
+               if(!XML_Parse(parser, buffer, len, done)) 
+               {
+                       MessageBox(0,L"Could not parse the xml file !",0,0);
+                       return FALSE;
+               }
+       }
+
+       XML_ParserFree(parser);
+       fclose(file);
+
+       return TRUE;
+}
+
+void FreeApps (struct Application* Apps)
+{
+       if (Apps->Next)
+               FreeApps(Apps->Next);
+
+       free(Apps);
+}
+
+void FreeTree (struct Category* Node)
+{
+       if (Node->Children)
+               FreeTree(Node->Children);
+
+       if (Node->Next)
+               FreeTree(Node->Next);
+
+       if (Node->Apps)
+               FreeApps(Node->Apps);
+
+       free(Node);
+}