示例#1
0
/*
MainDlgProc handles messages to the main dialog box
*/
INT_PTR CALLBACK MainDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	DIALOGPARAM *DlgParam = (DIALOGPARAM*)GetWindowLongPtr(hDlg, GWLP_USERDATA);
	HMENU listMenu;

	switch (msg) {
	case WM_INITDIALOG: {
		MCONTACT hContact;
		TCHAR title[256];
		TCHAR filter[FILTERTEXT];
		RECT rc;
		POINT pt;
			
		SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam);
		DlgParam = (DIALOGPARAM*)lParam;
		listMenu = GetMenu(hDlg);
		TranslateDialogDefault(hDlg);
		TranslateMenu(listMenu);

		hContact = ((db_get_b(NULL, LINKLIST_MODULE, LINKLIST_SAVESPECIAL, 0) == 0) ? NULL: DlgParam->hContact);
		if (db_get_b(hContact, LINKLIST_MODULE, LINKLIST_FIRST, 0) == 0) {
			// First use of this plugin! Set default size!
			db_set_dw(hContact, LINKLIST_MODULE, "LinklistWidth", 400);
			db_set_dw(hContact, LINKLIST_MODULE, "LinklistHeight", 450);
			db_set_dw(hContact, LINKLIST_MODULE, "LinklistX", 0);
			db_set_dw(hContact, LINKLIST_MODULE, "LinklistY", 0);
				
			db_set_b(hContact, LINKLIST_MODULE, LINKLIST_FIRST, 1);
		}

		DlgParam->splitterPosNew = (int)db_get_dw(hContact, LINKLIST_MODULE, LINKLIST_SPLITPOS, -1);

		GetWindowRect(GetDlgItem(hDlg, IDC_MAIN), &rc);
		DlgParam->minSize.cx = rc.right - rc.left;
		DlgParam->minSize.cy = rc.bottom - rc.top;

		GetWindowRect(GetDlgItem(hDlg, IDC_SPLITTER), &rc);
		pt.y = (rc.top + rc.bottom) / 2;
		pt.x = 0;
		ScreenToClient(hDlg, &pt);
			
		DlgParam->splitterPosOld = rc.bottom - 20 - pt.y;
		if(DlgParam->splitterPosNew == -1)
			DlgParam->splitterPosNew = DlgParam->splitterPosOld;
			
		Utils_RestoreWindowPosition(hDlg, hContact, LINKLIST_MODULE, "Linklist");

		SetClassLongPtr(hDlg, GCLP_HICON, (LONG_PTR)LoadIcon(hInst, MAKEINTRESOURCE(IDI_LINKLISTICON))); 
		WindowList_Add(hWindowList, hDlg, DlgParam->hContact);
		mir_sntprintf(title, _T("%s [%s]"), TranslateT("Linklist plugin"), pcli->pfnGetContactDisplayName(DlgParam->hContact, 0));
		SetWindowText(hDlg, title);
		GetFilterText(listMenu, filter, _countof(filter));
		SetDlgItemText(hDlg, IDC_STATUS, filter);
			
		mir_subclassWindow(GetDlgItem(hDlg, IDC_SPLITTER), SplitterProc);
			
		SendDlgItemMessage( hDlg, IDC_MAIN, EM_SETEVENTMASK, 0, (LPARAM)ENM_LINK);
		SendDlgItemMessage( hDlg, IDC_MAIN, EM_AUTOURLDETECT, TRUE, 0 );
		// This is used in srmm... and I think he knew what he did... :)
		SendDlgItemMessage(hDlg, IDC_MAIN, EM_LIMITTEXT, (WPARAM)-1, 0);

		WriteLinkList(hDlg, WLL_ALL, (LISTELEMENT*)DlgParam->listStart, NULL, 0);

		return TRUE;
		} break;
	// open browser an load url if link is pressed
	// found at
	// http://www.tech-archive.net/Archive/Development/microsoft.public.win32.programmer.ui/2004-03/0133.html
	//
	// Popup menu on right mouse button is mainly taken from the miranda 
	// send/receive messaging plugin.
	case WM_NOTIFY: {  
		if (lParam == NULL)
			break;
		if (((LPNMHDR)lParam)->code != EN_LINK)
			break;
		LPTSTR link;
		BYTE mouseEvent;
		ENLINK *pENLink = (ENLINK*)lParam;

		mouseEvent = db_get_b(NULL, LINKLIST_MODULE, LINKLIST_MOUSE_EVENT, 0xFF);

		switch (pENLink->msg) {
		case WM_MOUSEMOVE:
			if (mouseEvent != 0x01)
				break;
			memcpy(&DlgParam->chrg, &pENLink->chrg, sizeof(CHARRANGE));
			SendDlgItemMessage(hDlg, IDC_MAIN, EM_EXSETSEL, 0, (LPARAM)&pENLink->chrg);
			WriteMessage(hDlg, DlgParam->listStart, SendDlgItemMessage(hDlg, IDC_MAIN, EM_LINEFROMCHAR, -1, 0));
			break;
		case WM_LBUTTONUP:
			link = (LPTSTR)mir_alloc((pENLink->chrg.cpMax - pENLink->chrg.cpMin + 2) * sizeof(TCHAR));
			if (link == NULL)
				break;
			SendDlgItemMessage(hDlg, IDC_MAIN, EM_EXSETSEL, 0, (LPARAM)&pENLink->chrg); 
			SendDlgItemMessage(hDlg, IDC_MAIN, EM_GETSELTEXT, 0, (LPARAM)link);
			if (_tcsstr(link, _T("mailto:")) != NULL)
				ShellExecute(HWND_TOP, NULL, link, NULL, NULL, SW_SHOWNORMAL); 
			else {
				bool openNewWindow = db_get_b(NULL, LINKLIST_MODULE, LINKLIST_OPEN_WINDOW, 0xFF) != 0xFF;
				Utils_OpenUrlT(link,openNewWindow);
			}
			mir_free(link);
			break;
		case WM_RBUTTONDOWN: { 
			HMENU hPopup, hSubMenu;
			POINT pt;
			hPopup = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU2));
			hSubMenu = GetSubMenu(hPopup, 0);

			// Disable Menuoption if "mouse over" events are active
			mouseEvent = db_get_b(NULL, LINKLIST_MODULE, LINKLIST_MOUSE_EVENT, 0xFF);
			if (mouseEvent == 0x01)
				EnableMenuItem(hSubMenu, IDM_SHOWMESSAGE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);	
			TranslateMenu(hSubMenu);
			link = (LPTSTR)mir_alloc((pENLink->chrg.cpMax - pENLink->chrg.cpMin + 4) * sizeof(TCHAR));
			if (link == NULL)
				break;
			SendDlgItemMessage(hDlg, IDC_MAIN, EM_EXSETSEL, 0, (LPARAM)&pENLink->chrg); 
			SendDlgItemMessage(hDlg, IDC_MAIN, EM_GETSELTEXT, 0, (LPARAM)link);

			pt.x = (short)LOWORD(pENLink->lParam);
			pt.y = (short)HIWORD(pENLink->lParam);
			ClientToScreen(((NMHDR*)lParam)->hwndFrom, &pt);

			switch (TrackPopupMenu(hSubMenu, TPM_RETURNCMD, pt.x, pt.y, 0, hDlg, NULL)) {
			case IDM_LINK_OPEN:
				if (_tcsstr(link, _T("mailto:")) != NULL)
					ShellExecute(HWND_TOP, NULL, link, NULL, NULL, SW_SHOWNORMAL); 
				else
					Utils_OpenUrlT(link,false);
				break;
			case IDM_LINK_OPENNEW:
				if (_tcsstr(link, _T("mailto:")) != NULL)
					ShellExecute(HWND_TOP, NULL, link, NULL, NULL, SW_SHOWNORMAL); 
				else
					Utils_OpenUrlT(link);
				break;
			case IDM_LINK_COPY: {
				if (!OpenClipboard(hDlg))
					break;
				EmptyClipboard();

				size_t dataLen = ((mir_tstrlen(link) + 1) * sizeof(TCHAR));
				HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE, dataLen);
				memcpy((LPTSTR)GlobalLock(hData), link, dataLen);
				GlobalUnlock(hData);
				SetClipboardData(CF_UNICODETEXT, hData);
				CloseClipboard();
				} break;
			case IDM_SHOWMESSAGE:
				WriteMessage(hDlg, DlgParam->listStart, SendDlgItemMessage(hDlg, IDC_MAIN, EM_LINEFROMCHAR, -1, 0));
				break;
			}
			mir_free(link);
			DestroyMenu(hPopup);
			} break;
		}
		} break;
	case WM_COMMAND: {
		TCHAR filter[40];

		listMenu = GetMenu(hDlg);
		switch (wParam) {
		case IDM_SEARCH: // open Search Box
			if (DlgParam != 0) {	
				HWND hWndSearchDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_SEARCH_DLG), hDlg, SearchDlgProc, (LPARAM)DlgParam);
				EnableMenuItem(listMenu, IDM_SEARCH, (MF_BYCOMMAND | MF_DISABLED | MF_GRAYED));
				ShowWindow(hWndSearchDlg, SW_SHOW);
				SetFocus(GetDlgItem(hWndSearchDlg, IDC_SEARCHSTRING));
			}
			break;
		case IDM_CLEARSEARCH: // clear search results
			GetFilterText(listMenu, filter, _countof(filter));
			SetDlgItemText(hDlg, IDC_STATUS, filter);
			SetDlgItemText(hDlg, IDC_MAIN, _T(""));
			WriteLinkList(hDlg, GetFlags(listMenu), DlgParam->listStart, NULL, 0);
			break;
		case IDM_SAVE: // save button
			SaveEditAsStream(hDlg);
			SetFocus(GetDlgItem(hDlg, IDC_MAIN));
			break;
		case IDCANCEL: // Esc or Close pressed
		case IDM_CLOSE:
			SendMessage(hDlg, WM_CLOSE, 0, 0);
			break;
		case IDM_DIR_IN: // view only incoming messages
			GetFilterText(listMenu, filter, _countof(filter));
			SetDlgItemText(hDlg, IDC_STATUS, filter);
			if ((GetMenuState(listMenu, IDM_SEARCH, MF_BYCOMMAND) & MF_DISABLED))
				break; // not possible if search dialog is open
			SetDlgItemText(hDlg, IDC_MAIN, _T(""));
			if (GetMenuState(listMenu, IDM_DIR_IN, MF_BYCOMMAND) == MF_CHECKED) {
				CheckMenuItem(listMenu, IDM_DIR_IN, MF_UNCHECKED);
				WriteLinkList(hDlg, GetFlags(listMenu), DlgParam->listStart, NULL, 0);
			} else {
				CheckMenuItem(listMenu, IDM_DIR_IN, MF_CHECKED);
				CheckMenuItem(listMenu, IDM_DIR_OUT, MF_UNCHECKED);
				WriteLinkList(hDlg, GetFlags(listMenu), DlgParam->listStart, NULL, 0);
			}		
			GetFilterText(GetMenu(hDlg), filter, _countof(filter));
			SetDlgItemText(hDlg, IDC_STATUS, filter);
			break;
		case IDM_DIR_OUT: // view only outgoing messages
			GetFilterText(listMenu, filter, _countof(filter));
			SetDlgItemText(hDlg, IDC_STATUS, filter);
			if ((GetMenuState(listMenu, IDM_SEARCH, MF_BYCOMMAND) & MF_DISABLED))
				break; // not possible if search dialog is open
			SetDlgItemText(hDlg, IDC_MAIN, _T(""));
			if (GetMenuState(listMenu, IDM_DIR_OUT, MF_BYCOMMAND) == MF_CHECKED) {
				CheckMenuItem(listMenu, IDM_DIR_OUT, MF_UNCHECKED);		
				WriteLinkList(hDlg, GetFlags(listMenu), DlgParam->listStart, NULL, 0);
			} else {
				CheckMenuItem(listMenu, IDM_DIR_OUT, MF_CHECKED);
				CheckMenuItem(listMenu, IDM_DIR_IN, MF_UNCHECKED);
				WriteLinkList(hDlg, GetFlags(listMenu), DlgParam->listStart, NULL, 0);
			}
			GetFilterText(listMenu, filter, _countof(filter));
			SetDlgItemText(hDlg, IDC_STATUS, filter);
			break;
		case IDM_TYPE_WEB: // view only e-mail addresses
			GetFilterText(listMenu, filter, _countof(filter));
			SetDlgItemText(hDlg, IDC_STATUS, filter);
			// not possible if search dialog is open
			if ((GetMenuState(listMenu, IDM_SEARCH, MF_BYCOMMAND) & MF_DISABLED))
				break;
			SetDlgItemText(hDlg, IDC_MAIN, _T(""));
			if (GetMenuState(listMenu, IDM_TYPE_WEB, MF_BYCOMMAND) == MF_CHECKED) {
				CheckMenuItem(listMenu, IDM_TYPE_WEB, MF_UNCHECKED);		
				WriteLinkList(hDlg, GetFlags(listMenu), DlgParam->listStart, NULL, 0);
			} else {
				CheckMenuItem(listMenu, IDM_TYPE_WEB, MF_CHECKED);
				CheckMenuItem(listMenu, IDM_TYPE_MAIL, MF_UNCHECKED);
				WriteLinkList(hDlg, GetFlags(listMenu), DlgParam->listStart, NULL, 0);
			}
			GetFilterText(listMenu, filter, _countof(filter));
			SetDlgItemText(hDlg, IDC_STATUS, filter);
			break;
		case IDM_TYPE_MAIL: // view only URLs
			if ((GetMenuState(listMenu, IDM_SEARCH, MF_BYCOMMAND) & MF_DISABLED))
				break; // not possible if search dialog is open
			SetDlgItemText(hDlg, IDC_MAIN, _T(""));
			if (GetMenuState(listMenu, IDM_TYPE_MAIL, MF_BYCOMMAND) == MF_CHECKED) {
				CheckMenuItem(listMenu, IDM_TYPE_MAIL, MF_UNCHECKED);		
				WriteLinkList(hDlg, GetFlags(listMenu), DlgParam->listStart, NULL, 0);				
			} else {
				CheckMenuItem(listMenu, IDM_TYPE_MAIL, MF_CHECKED);
				CheckMenuItem(listMenu, IDM_TYPE_WEB, MF_UNCHECKED);
				WriteLinkList(hDlg, GetFlags(listMenu), DlgParam->listStart, NULL, 0);
			}
			GetFilterText(listMenu, filter, _countof(filter));
			SetDlgItemText(hDlg, IDC_STATUS, filter);
			break;
		}
		} break;
	// Taken from srmm.
	// Btw: The longer I searched the source of this plugin
	// to learn how things work, the more I became a fan of
	// the programmer! 
	case WM_GETMINMAXINFO: {
		MINMAXINFO *mmi = (MINMAXINFO *)lParam;
		RECT rcWindow, rcMain;

		GetWindowRect(hDlg, &rcWindow);
		GetWindowRect(GetDlgItem(hDlg, IDC_MAIN), &rcMain);
		mmi->ptMinTrackSize.x = rcWindow.right - rcWindow.left - ((rcMain.right - rcMain.left) - DlgParam->minSize.cx);
		mmi->ptMinTrackSize.y = rcWindow.bottom - rcWindow.top - ((rcMain.bottom - rcMain.top) - DlgParam->minSize.cy);
		} break;
	case WM_SIZE:
		Utils_ResizeDialog(hDlg, hInst, MAKEINTRESOURCEA(IDD_MAIN_DLG), LinklistResizer, (LPARAM)DlgParam);
		// To get some scrollbars if needed...
		RedrawWindow(GetDlgItem(hDlg, IDC_MAIN), NULL, NULL, RDW_INVALIDATE);
		RedrawWindow(GetDlgItem(hDlg, IDC_MESSAGE), NULL, NULL, RDW_INVALIDATE);
		break;
	
	case DM_LINKSPLITTER: {
		POINT pt;
		RECT rc;
		int splitPosOld;

		GetClientRect(hDlg, &rc);
		pt.x = 0;
		pt.y = wParam;
		ScreenToClient(hDlg, &pt);

		splitPosOld = DlgParam->splitterPosNew;
		DlgParam->splitterPosNew = rc.bottom - pt.y;
			
		GetWindowRect(GetDlgItem(hDlg, IDC_MESSAGE), &rc);
		if (rc.bottom - rc.top + (DlgParam->splitterPosNew - splitPosOld) < 0)
			DlgParam->splitterPosNew = splitPosOld + 0 - (rc.bottom - rc.top);

		GetWindowRect(GetDlgItem(hDlg, IDC_MAIN), &rc);
		if (rc.bottom - rc.top - (DlgParam->splitterPosNew - splitPosOld) < DlgParam->minSize.cy)
			DlgParam->splitterPosNew = splitPosOld - DlgParam->minSize.cy + (rc.bottom - rc.top);
		SendMessage(hDlg, WM_SIZE, 0, 0);
		} break;
	case WM_CLOSE:
		DestroyWindow(hDlg);
		break;
	case WM_DESTROY:
		if (DlgParam != NULL) {
			MCONTACT hContact = ((db_get_b(NULL, LINKLIST_MODULE, LINKLIST_SAVESPECIAL, 0) == 0) ? NULL: DlgParam->hContact);
			Utils_SaveWindowPosition(hDlg, hContact, LINKLIST_MODULE, "Linklist");
			db_set_dw(NULL, LINKLIST_MODULE, LINKLIST_SPLITPOS, DlgParam->splitterPosNew);
			RemoveList(DlgParam->listStart);
			mir_free(DlgParam);
		}
		// Remove entry from Window list
		WindowList_Remove(hWindowList, hDlg);
		break;
	}
	return FALSE;
}
示例#2
0
/*
This function handles the search dialog messages
*/
INT_PTR CALLBACK SearchDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
	HWND hListDlg;
	DIALOGPARAM *DlgParam  = (DIALOGPARAM *)GetWindowLongPtr(hDlg, GWLP_USERDATA);

	switch (msg) {
	case WM_INITDIALOG:
		TranslateDialogDefault(hDlg);
		SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)lParam);
		SetWindowText(hDlg, TXT_SEARCH);
		CheckDlgButton(hDlg, IDC_DIR_ALL, BST_CHECKED);
		CheckDlgButton(hDlg, IDC_TYPE_ALL, BST_CHECKED);
		return TRUE;
		break;
	case WM_COMMAND: {
		HWND hWndMain;
		hWndMain = WindowList_Find(hWindowList,DlgParam->hContact);
			
		switch (wParam) {
		case IDCLOSE:
		case IDCANCEL: {
			HMENU listMenu = GetMenu(hWndMain);
			EnableMenuItem(listMenu, 101, MF_BYCOMMAND | MF_ENABLED);
			DestroyWindow(hDlg);
			return TRUE;
			} break;
		case IDSEARCH: {
			BYTE flags = 0x00;
			TCHAR filter[FILTERTEXT];
			LPTSTR buffer;
			int length;
			
			hListDlg = WindowList_Find(hWindowList, DlgParam->hContact);
			if (hListDlg == NULL)
				break;
			SetDlgItemText(hListDlg, IDC_MAIN, _T(""));
			if (IsDlgButtonChecked(hDlg, IDC_TYPE_WEB) == BST_UNCHECKED)
				flags |= WLL_MAIL;
			if (IsDlgButtonChecked(hDlg, IDC_TYPE_MAIL) == BST_UNCHECKED)
				flags |= WLL_URL;
			if (IsDlgButtonChecked(hDlg, IDC_DIR_IN) == BST_UNCHECKED)
				flags |= WLL_OUT;
			if (IsDlgButtonChecked(hDlg, IDC_DIR_OUT) == BST_UNCHECKED)
				flags |= WLL_IN;					
			if (IsDlgButtonChecked(hDlg, IDC_WHOLE_MESSAGE) == BST_CHECKED)
				flags |= SLL_DEEP;

			length = GetWindowTextLength(GetDlgItem(hDlg, IDC_SEARCHSTRING)) + 1;
			buffer = (LPTSTR)mir_alloc((length + 1) * sizeof(TCHAR));
			if (buffer) {
				GetDlgItemText(hDlg, IDC_SEARCHSTRING, buffer, length);
				WriteLinkList(hListDlg, flags, DlgParam->listStart, buffer, 0);
				mir_free(buffer);
			}		
			mir_sntprintf(filter, _T("%s: %s"), TXT_FILTER, TXT_SEARCHFILTER);
			SetDlgItemText(hWndMain, IDC_STATUS, filter);
			} break;
		}
		} break;
	}
	return FALSE;
}
示例#3
0
int main()
{
  HANDLE fout, fin;
  DWORD bytes_read, bytes_written;
  InstData *idata;
  InstFiles *filept;
  char *inbuf, *outbuf;
  int status, count;
  bstr *str;
#ifdef LIBBZ2
  bz_stream z;
#else
  z_stream z;
#endif

  idata = ReadInstallData();

  fout = CreateFile("installfiles.z", GENERIC_WRITE, 0, NULL,
                    CREATE_ALWAYS, 0, NULL);

  outbuf = bmalloc(BUFFER_SIZE);
  inbuf = bmalloc(BUFFER_SIZE);

#ifdef LIBBZ2
  z.bzalloc = NULL;
  z.bzfree = NULL;
  z.opaque = NULL;
  BZ2_bzCompressInit(&z, COMPRESSION, 0, 30);
#else
  z.zalloc = Z_NULL;
  z.zfree  = Z_NULL;
  z.opaque = Z_NULL;
  deflateInit(&z, COMPRESSION);
#endif
  z.avail_in = 0;
  z.next_out = outbuf;
  z.avail_out = BUFFER_SIZE;

  filept = NULL;
  fin = NULL;
  OpenNextFile(idata->instfiles, &filept, &fin);
  if (fin == INVALID_HANDLE_VALUE) {
    return 1;
  }

  while (fin != INVALID_HANDLE_VALUE) {
    if (z.avail_in == 0) {
      z.next_in = inbuf;
      bytes_read = 0;
      while (!bytes_read && fin) {
        if (!ReadFile(fin, inbuf, BUFFER_SIZE, &bytes_read, NULL)) {
          printf("Read error\n");
          break;
        }
        filept->filesize += bytes_read;
        if (!bytes_read)
          OpenNextFile(idata->instfiles, &filept, &fin);
      }
      z.avail_in = bytes_read;
    }
#ifdef LIBBZ2
    status = BZ2_bzCompress(&z, z.avail_in == 0 ? BZ_FINISH : BZ_RUN);
#else
    status = deflate(&z, z.avail_in == 0 ? Z_FINISH : Z_NO_FLUSH);
#endif
    count = BUFFER_SIZE - z.avail_out;
    if (!WriteFile(fout, outbuf, count, &bytes_written, NULL)) {
      printf("Write error\n");
    }
    z.next_out = outbuf;
    z.avail_out = BUFFER_SIZE;

#ifdef LIBBZ2
    if (status == BZ_STREAM_END) {
      break;
    } else if (status != BZ_RUN_OK && status != BZ_FINISH_OK) {
      printf("Unexpected bzlib status: %d\n", status);
      break;
    }
#else
    if (status == Z_STREAM_END) {
      break;
    } else if (status != Z_OK) {
      printf("Unexpected libz status: %d\n", status);
      break;
    }
#endif
  }

#ifdef LIBBZ2
  printf("Written compressed data: raw %d, compressed %d\n",
         z.total_in_lo32, z.total_out_lo32);
  bytes_written = z.total_out_lo32;
  BZ2_bzCompressEnd(&z);
#else
  printf("Written compressed data: raw %ld, compressed %ld\n",
         z.total_in, z.total_out);
  bytes_written = z.total_out;
  deflateEnd(&z);
#endif

  CloseHandle(fout);

  fout = CreateFile("manifest", GENERIC_WRITE, 0, NULL,
                    CREATE_ALWAYS, 0, NULL);
  if (fout == INVALID_HANDLE_VALUE)
    printf("Cannot create file list\n");

  str = bstr_new();
  bstr_setlength(str, 0);
  bstr_append_long(str, bytes_written);
  if (!WriteFile(fout, str->text, str->length + 1, &bytes_written, NULL)) {
    printf("Write error\n");
  }

  if (!WriteFile(fout, idata->product, strlen(idata->product) + 1,
                 &bytes_written, NULL)) {
    printf("Write error\n");
  }
  if (!WriteFile(fout, idata->installdir, strlen(idata->installdir) + 1,
                 &bytes_written, NULL)) {
    printf("Write error\n");
  }
  if (!WriteFile
      (fout, idata->startmenudir, strlen(idata->startmenudir) + 1,
       &bytes_written, NULL)) {
    printf("Write error\n");
  }

  WriteFileList(fout, idata->instfiles);
  WriteFileList(fout, idata->extrafiles);

  WriteLinkList(fout, idata->startmenu);
  WriteLinkList(fout, idata->desktop);

  WriteServiceDetails(fout, idata->service);
  WriteFileList(fout, idata->keepfiles);

  CloseHandle(fout);
  bfree(inbuf);
  bfree(outbuf);

  FreeInstData(idata, TRUE);

  return 0;
}