예제 #1
0
INT_PTR CALLBACK DlgProcRecvFile(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
    struct FileDlgData *dat;

    dat = (struct FileDlgData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
    switch (msg) {
    case WM_INITDIALOG:
        TranslateDialogDefault(hwndDlg);
        {
            TCHAR szPath[450];
            CLISTEVENT* cle = (CLISTEVENT*)lParam;


            dat = (struct FileDlgData*)mir_calloc(sizeof(struct FileDlgData));
            SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
            dat->hContact = cle->hContact;
            dat->hDbEvent = cle->hDbEvent;
            dat->hPreshutdownEvent = HookEventMessage(ME_SYSTEM_PRESHUTDOWN, hwndDlg, M_PRESHUTDOWN);
            dat->dwTicks = GetTickCount();

            EnumChildWindows(hwndDlg, ClipSiblingsChildEnumProc, 0);

            Window_SetIcon_IcoLib(hwndDlg, SKINICON_EVENT_FILE);
            Button_SetIcon_IcoLib(hwndDlg, IDC_ADD, SKINICON_OTHER_ADDCONTACT, LPGEN("Add contact permanently to list"));
            Button_SetIcon_IcoLib(hwndDlg, IDC_DETAILS, SKINICON_OTHER_USERDETAILS, LPGEN("View user's details"));
            Button_SetIcon_IcoLib(hwndDlg, IDC_HISTORY, SKINICON_OTHER_HISTORY, LPGEN("View user's history"));
            Button_SetIcon_IcoLib(hwndDlg, IDC_USERMENU, SKINICON_OTHER_DOWNARROW, LPGEN("User menu"));

            TCHAR *contactName = pcli->pfnGetContactDisplayName(dat->hContact, 0);
            SetDlgItemText(hwndDlg, IDC_FROM, contactName);
            GetContactReceivedFilesDir(dat->hContact, szPath, SIZEOF(szPath), TRUE);
            SetDlgItemText(hwndDlg, IDC_FILEDIR, szPath);
            SHAutoComplete(GetWindow(GetDlgItem(hwndDlg, IDC_FILEDIR), GW_CHILD), 1);

            for (int i=0; i < MAX_MRU_DIRS; i++) {
                char idstr[32];
                mir_snprintf(idstr, SIZEOF(idstr), "MruDir%d", i);

                DBVARIANT dbv;
                if (db_get_ts(NULL, "SRFile", idstr, &dbv))
                    break;
                SendDlgItemMessage(hwndDlg, IDC_FILEDIR, CB_ADDSTRING, 0, (LPARAM)dbv.ptszVal);
                db_free(&dbv);
            }

            db_event_markRead(dat->hContact, dat->hDbEvent);

            DBEVENTINFO dbei = { sizeof(dbei) };
            dbei.cbBlob = db_event_getBlobSize(dat->hDbEvent);
            if (dbei.cbBlob > 4 && dbei.cbBlob <= 8196) {
                dbei.pBlob = (PBYTE)alloca(dbei.cbBlob + 1);
                db_event_get(dat->hDbEvent, &dbei);
                dbei.pBlob[dbei.cbBlob] = 0;
                dat->fs = cle->lParam ? (HANDLE)cle->lParam : (HANDLE)*(PDWORD)dbei.pBlob;

                char *str = (char*)dbei.pBlob + 4;
                ptrT ptszFileName( DbGetEventStringT(&dbei, str));
                SetDlgItemText(hwndDlg, IDC_FILENAMES, ptszFileName);

                unsigned len = (unsigned)strlen(str) + 1;
                if (len + 4 < dbei.cbBlob) {
                    str += len;
                    ptrT ptszDescription( DbGetEventStringT(&dbei, str));
                    SetDlgItemText(hwndDlg, IDC_MSG, ptszDescription);
                }
            }
            else DestroyWindow(hwndDlg);

            TCHAR datetimestr[64];
            tmi.printTimeStamp(NULL, dbei.timestamp, _T("t d"), datetimestr, SIZEOF(datetimestr), 0);
            SetDlgItemText(hwndDlg, IDC_DATE, datetimestr);

            char* szProto = GetContactProto(dat->hContact);
            if (szProto) {
                int hasName = 0;
                char buf[128];

                CONTACTINFO ci = { 0 };
                ci.cbSize = sizeof(ci);
                ci.hContact = dat->hContact;
                ci.szProto = szProto;
                ci.dwFlag = CNF_UNIQUEID;
                if ( !CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM)&ci)) {
                    switch(ci.type) {
                    case CNFT_ASCIIZ:
                        hasName = 1;
                        mir_snprintf(buf, SIZEOF(buf), "%s", ci.pszVal);
                        mir_free(ci.pszVal);
                        break;
                    case CNFT_DWORD:
                        hasName = 1;
                        mir_snprintf(buf, SIZEOF(buf), "%u", ci.dVal);
                        break;
                    }
                }
                if (hasName)
                    SetDlgItemTextA(hwndDlg, IDC_NAME, buf);
                else
                    SetDlgItemText(hwndDlg, IDC_NAME, contactName);
            }

            if (db_get_b(dat->hContact, "CList", "NotOnList", 0)) {
                RECT rcBtn1, rcBtn2, rcDateCtrl;
                GetWindowRect(GetDlgItem(hwndDlg, IDC_ADD), &rcBtn1);
                GetWindowRect(GetDlgItem(hwndDlg, IDC_USERMENU), &rcBtn2);
                GetWindowRect(GetDlgItem(hwndDlg, IDC_DATE), &rcDateCtrl);
                SetWindowPos(GetDlgItem(hwndDlg, IDC_DATE), 0, 0, 0, rcDateCtrl.right-rcDateCtrl.left-(rcBtn2.left-rcBtn1.left), rcDateCtrl.bottom-rcDateCtrl.top, SWP_NOZORDER|SWP_NOMOVE);
            }
            else if (db_get_b(NULL, "SRFile", "AutoAccept", 0)) {
                //don't check auto-min here to fix BUG#647620
                PostMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDOK, BN_CLICKED), (LPARAM)GetDlgItem(hwndDlg, IDOK));
            }
            if ( !db_get_b(dat->hContact, "CList", "NotOnList", 0))
                ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), SW_HIDE);
        }
        return TRUE;

    case WM_MEASUREITEM:
        return CallService(MS_CLIST_MENUMEASUREITEM, wParam, lParam);

    case WM_DRAWITEM:
    {
        LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
        if (dis->hwndItem == GetDlgItem(hwndDlg, IDC_PROTOCOL)) {
            char *szProto = GetContactProto(dat->hContact);
            if (szProto) {
                HICON hIcon = (HICON)CallProtoService(szProto, PS_LOADICON, PLI_PROTOCOL|PLIF_SMALL, 0);
                if (hIcon) {
                    DrawIconEx(dis->hDC, dis->rcItem.left, dis->rcItem.top, hIcon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL);
                    DestroyIcon(hIcon);
                }
            }
        }
    }
    return CallService(MS_CLIST_MENUDRAWITEM, wParam, lParam);

    case WM_COMMAND:
        if (CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM)dat->hContact))
            break;

        switch (LOWORD(wParam)) {
        case IDC_FILEDIRBROWSE:
        {
            TCHAR szDirName[MAX_PATH], szExistingDirName[MAX_PATH];

            GetDlgItemText(hwndDlg, IDC_FILEDIR, szDirName, SIZEOF(szDirName));
            GetLowestExistingDirName(szDirName, szExistingDirName, SIZEOF(szExistingDirName));
            if (BrowseForFolder(hwndDlg, szExistingDirName))
                SetDlgItemText(hwndDlg, IDC_FILEDIR, szExistingDirName);
        }
        break;

        case IDOK:
        {   //most recently used directories
            TCHAR szRecvDir[MAX_PATH], szDefaultRecvDir[MAX_PATH];
            GetDlgItemText(hwndDlg, IDC_FILEDIR, szRecvDir, SIZEOF(szRecvDir));
            RemoveInvalidPathChars(szRecvDir);
            GetContactReceivedFilesDir(NULL, szDefaultRecvDir, SIZEOF(szDefaultRecvDir), TRUE);
            if (_tcsnicmp(szRecvDir, szDefaultRecvDir, lstrlen(szDefaultRecvDir))) {
                char idstr[32];
                int i;
                DBVARIANT dbv;
                for (i = MAX_MRU_DIRS-2; i>=0; i--) {
                    mir_snprintf(idstr, SIZEOF(idstr), "MruDir%d", i);
                    if (db_get_ts(NULL, "SRFile", idstr, &dbv)) continue;
                    mir_snprintf(idstr, SIZEOF(idstr), "MruDir%d", i+1);
                    db_set_ts(NULL, "SRFile", idstr, dbv.ptszVal);
                    db_free(&dbv);
                }
                db_set_ts(NULL, "SRFile", idstr, szRecvDir);
            }
        }
        EnableWindow(GetDlgItem(hwndDlg, IDC_FILENAMES), FALSE);
        EnableWindow(GetDlgItem(hwndDlg, IDC_MSG), FALSE);
        EnableWindow(GetDlgItem(hwndDlg, IDC_FILEDIR), FALSE);
        EnableWindow(GetDlgItem(hwndDlg, IDC_FILEDIRBROWSE), FALSE);

        GetDlgItemText(hwndDlg, IDC_FILEDIR, dat->szSavePath, SIZEOF(dat->szSavePath));
        GetDlgItemText(hwndDlg, IDC_FILE, dat->szFilenames, SIZEOF(dat->szFilenames));
        GetDlgItemText(hwndDlg, IDC_MSG, dat->szMsg, SIZEOF(dat->szMsg));
        dat->hwndTransfer = FtMgr_AddTransfer(dat);
        SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
            //check for auto-minimize here to fix BUG#647620
        if (db_get_b(NULL, "SRFile", "AutoAccept", 0) && db_get_b(NULL, "SRFile", "AutoMin", 0)) {
            ShowWindow(hwndDlg, SW_HIDE);
            ShowWindow(hwndDlg, SW_SHOWMINNOACTIVE);
        }
        DestroyWindow(hwndDlg);
        break;

        case IDCANCEL:
            if (dat->fs) CallContactService(dat->hContact, PSS_FILEDENYT, (WPARAM)dat->fs, (LPARAM)TranslateT("Canceled"));
            dat->fs = NULL; /* the protocol will free the handle */
            DestroyWindow(hwndDlg);
            break;

        case IDC_ADD:
        {   ADDCONTACTSTRUCT acs = {0};

            acs.handle = dat->hContact;
            acs.handleType = HANDLE_CONTACT;
            acs.szProto = "";
            CallService(MS_ADDCONTACT_SHOW, (WPARAM)hwndDlg, (LPARAM)&acs);
            if ( !db_get_b(dat->hContact, "CList", "NotOnList", 0))
                ShowWindow(GetDlgItem(hwndDlg, IDC_ADD), SW_HIDE);
        }
        break;

        case IDC_USERMENU:
        {   RECT rc;
            HMENU hMenu = (HMENU)CallService(MS_CLIST_MENUBUILDCONTACT, (WPARAM)dat->hContact, 0);
            GetWindowRect((HWND)lParam, &rc);
            TrackPopupMenu(hMenu, 0, rc.left, rc.bottom, 0, hwndDlg, NULL);
            DestroyMenu(hMenu);
        }
        break;

        case IDC_DETAILS:
            CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)dat->hContact, 0);
            break;

        case IDC_HISTORY:
            CallService(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM)dat->hContact, 0);
            break;
        }
        break;

    case WM_DESTROY:
        Window_FreeIcon_IcoLib(hwndDlg);
        Button_FreeIcon_IcoLib(hwndDlg, IDC_ADD);
        Button_FreeIcon_IcoLib(hwndDlg, IDC_DETAILS);
        Button_FreeIcon_IcoLib(hwndDlg, IDC_HISTORY);
        Button_FreeIcon_IcoLib(hwndDlg, IDC_USERMENU);

        if (dat) FreeFileDlgData(dat);
        break;
    }
    return FALSE;
}
예제 #2
0
INT_PTR CALLBACK DlgProcFileTransfer(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	FileDlgData *dat = (FileDlgData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);

	switch (msg) {
	case WM_INITDIALOG:
		TranslateDialogDefault(hwndDlg);
		dat = (FileDlgData*)lParam;
		SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
		dat->hNotifyEvent = HookEventMessage(ME_PROTO_ACK, hwndDlg, HM_RECVEVENT);
		dat->transferStatus.currentFileNumber = -1;
		if (dat->send) {
			if (db_mc_isMeta(dat->hContact))
				dat->hContact = db_mc_getMostOnline(dat->hContact);
			dat->fs = (HANDLE)CallContactService(dat->hContact, PSS_FILE, (WPARAM)dat->szMsg, (LPARAM)dat->files);
			SetFtStatus(hwndDlg, LPGENT("Request sent, waiting for acceptance..."), FTS_TEXT);
			SetOpenFileButtonStyle(GetDlgItem(hwndDlg, IDC_OPENFILE), 1);
			dat->waitingForAcceptance = 1;
			// hide "open" button since it may cause potential access violations...
			ShowWindow(GetDlgItem(hwndDlg, IDC_OPENFILE), SW_HIDE);
			ShowWindow(GetDlgItem(hwndDlg, IDC_OPENFOLDER), SW_HIDE);
		}
		else {	//recv
			CreateDirectoryTreeT(dat->szSavePath);
			dat->fs = (HANDLE)CallContactService(dat->hContact, PSS_FILEALLOW, (WPARAM)dat->fs, (LPARAM)dat->szSavePath);
			dat->transferStatus.tszWorkingDir = mir_tstrdup(dat->szSavePath);
			if (db_get_b(dat->hContact, "CList", "NotOnList", 0)) dat->resumeBehaviour = FILERESUME_ASK;
			else dat->resumeBehaviour = db_get_b(NULL, "SRFile", "IfExists", FILERESUME_ASK);
			SetFtStatus(hwndDlg, LPGENT("Waiting for connection..."), FTS_TEXT);
		}

		/* check we actually got an fs handle back from the protocol */
		if (!dat->fs) {
			SetFtStatus(hwndDlg, LPGENT("Unable to initiate transfer."), FTS_TEXT);
			dat->waitingForAcceptance = 0;
		}
		{
			LOGFONT lf;
			HFONT hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_CONTACTNAME, WM_GETFONT, 0, 0);
			GetObject(hFont, sizeof(lf), &lf);
			lf.lfWeight = FW_BOLD;
			hFont = CreateFontIndirect(&lf);
			SendDlgItemMessage(hwndDlg, IDC_CONTACTNAME, WM_SETFONT, (WPARAM)hFont, 0);

			SHFILEINFO shfi = { 0 };
			SHGetFileInfo(_T(""), FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_SMALLICON);
			dat->hIconFolder = shfi.hIcon;
		}
		dat->hIcon = NULL;
		{
			char *szProto = GetContactProto(dat->hContact);
			WORD status = db_get_w(dat->hContact, szProto, "Status", ID_STATUS_ONLINE);
			SendDlgItemMessage(hwndDlg, IDC_CONTACT, BM_SETIMAGE, IMAGE_ICON, (LPARAM)Skin_LoadProtoIcon(szProto, status));
		}

		SendDlgItemMessage(hwndDlg, IDC_CONTACT, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Contact menu"), 0);
		SendDlgItemMessage(hwndDlg, IDC_CONTACT, BUTTONSETASFLATBTN, TRUE, 0);

		Button_SetIcon_IcoLib(hwndDlg, IDC_OPENFILE, SKINICON_OTHER_DOWNARROW, LPGEN("Open..."));
		SendDlgItemMessage(hwndDlg, IDC_OPENFILE, BUTTONSETASPUSHBTN, TRUE, 0);

		SendDlgItemMessage(hwndDlg, IDC_OPENFOLDER, BM_SETIMAGE, IMAGE_ICON, (LPARAM)dat->hIconFolder);
		SendDlgItemMessage(hwndDlg, IDC_OPENFOLDER, BUTTONADDTOOLTIP, (WPARAM)LPGEN("Open folder"), 0);
		SendDlgItemMessage(hwndDlg, IDC_OPENFOLDER, BUTTONSETASFLATBTN, TRUE, 0);

		Button_SetIcon_IcoLib(hwndDlg, IDCANCEL, SKINICON_OTHER_DELETE, LPGEN("Cancel"));

		SetDlgItemText(hwndDlg, IDC_CONTACTNAME, pcli->pfnGetContactDisplayName(dat->hContact, 0));

		if (!dat->waitingForAcceptance) SetTimer(hwndDlg, 1, 1000, NULL);
		return TRUE;

	case WM_TIMER:
		memmove(dat->bytesRecvedHistory + 1, dat->bytesRecvedHistory, sizeof(dat->bytesRecvedHistory) - sizeof(dat->bytesRecvedHistory[0]));
		dat->bytesRecvedHistory[0] = dat->transferStatus.totalProgress;
		if (dat->bytesRecvedHistorySize < _countof(dat->bytesRecvedHistory))
			dat->bytesRecvedHistorySize++;

		{
			TCHAR szSpeed[32], szTime[32], szDisplay[96];
			SYSTEMTIME st;
			ULARGE_INTEGER li;
			FILETIME ft;

			GetSensiblyFormattedSize((dat->bytesRecvedHistory[0] - dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]) / dat->bytesRecvedHistorySize, szSpeed, _countof(szSpeed), 0, 1, NULL);
			if (dat->bytesRecvedHistory[0] == dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1])
				mir_tstrcpy(szTime, _T("??:??:??"));
			else {
				li.QuadPart = BIGI(10000000)*(dat->transferStatus.currentFileSize - dat->transferStatus.currentFileProgress)*dat->bytesRecvedHistorySize / (dat->bytesRecvedHistory[0] - dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]);
				ft.dwHighDateTime = li.HighPart; ft.dwLowDateTime = li.LowPart;
				FileTimeToSystemTime(&ft, &st);
				GetTimeFormat(LOCALE_USER_DEFAULT, TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER, &st, NULL, szTime, _countof(szTime));
			}
			if (dat->bytesRecvedHistory[0] != dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]) {
				li.QuadPart = BIGI(10000000)*(dat->transferStatus.totalBytes - dat->transferStatus.totalProgress)*dat->bytesRecvedHistorySize / (dat->bytesRecvedHistory[0] - dat->bytesRecvedHistory[dat->bytesRecvedHistorySize - 1]);
				ft.dwHighDateTime = li.HighPart; ft.dwLowDateTime = li.LowPart;
				FileTimeToSystemTime(&ft, &st);
				GetTimeFormat(LOCALE_USER_DEFAULT, TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER, &st, NULL, szTime, _countof(szTime));
			}

			mir_sntprintf(szDisplay, _T("%s/%s  (%s %s)"), szSpeed, TranslateT("sec"), szTime, TranslateT("remaining"));
			SetDlgItemText(hwndDlg, IDC_ALLSPEED, szDisplay);
		}
		break;

	case WM_MEASUREITEM:
		return Menu_MeasureItem((LPMEASUREITEMSTRUCT)lParam);

	case WM_DRAWITEM:
		return Menu_DrawItem((LPDRAWITEMSTRUCT)lParam);

	case WM_FT_CLEANUP:
		if (!dat->fs) {
			PostMessage(GetParent(hwndDlg), WM_FT_REMOVE, 0, (LPARAM)hwndDlg);
			DestroyWindow(hwndDlg);
		}
		break;

	case WM_COMMAND:
		if (!dat)
			break;

		if (CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM)dat->hContact))
			break;

		switch (LOWORD(wParam)) {
		case IDOK:
		case IDCANCEL:
			PostMessage(GetParent(hwndDlg), WM_FT_REMOVE, 0, (LPARAM)hwndDlg);
			DestroyWindow(hwndDlg);
			break;

		case IDC_CONTACT:
			{
				RECT rc;
				HMENU hMenu = Menu_BuildContactMenu(dat->hContact);
				GetWindowRect((HWND)lParam, &rc);
				TrackPopupMenu(hMenu, 0, rc.left, rc.bottom, 0, hwndDlg, NULL);
				DestroyMenu(hMenu);
			}
			break;

		case IDC_TRANSFERCOMPLETED:
			if (dat->transferStatus.currentFileNumber <= 1 && CheckVirusScanned(hwndDlg, dat, 0)) {
				ShellExecute(NULL, NULL, dat->files[0], NULL, NULL, SW_SHOW);
				break;
			}

		case IDC_OPENFOLDER:
			{
				TCHAR *path = dat->transferStatus.tszWorkingDir;
				if (!path || !path[0]) {
					path = NEWTSTR_ALLOCA(dat->transferStatus.tszCurrentFile);
					TCHAR *p = _tcsrchr(path, '\\'); if (p) *p = 0;
				}

				if (path) ShellExecute(NULL, _T("open"), path, NULL, NULL, SW_SHOW);
			}
			break;

		case IDC_OPENFILE:
			TCHAR **files;
			if (dat->send) {
				if (dat->files == NULL)
					files = dat->transferStatus.ptszFiles;
				else
					files = dat->files;
			}
			else files = dat->files;

			HMENU hMenu = CreatePopupMenu();
			AppendMenu(hMenu, MF_STRING, 1, TranslateT("Open folder"));
			AppendMenu(hMenu, MF_SEPARATOR, 0, 0);

			if (files && *files) {
				int limit;
				TCHAR *pszFilename, *pszNewFileName;

				if (dat->send)
					limit = dat->transferStatus.totalFiles;
				else
					limit = dat->transferStatus.currentFileNumber;

				// Loop over all transfered files and add them to the menu
				for (int i = 0; i < limit; i++) {
					pszFilename = _tcsrchr(files[i], '\\');
					if (pszFilename == NULL)
						pszFilename = files[i];
					else
						pszFilename++;

					if (pszFilename) {
						size_t cbFileNameLen = mir_tstrlen(pszFilename);

						pszNewFileName = (TCHAR*)mir_alloc(cbFileNameLen * 2 * sizeof(TCHAR));
						TCHAR *p = pszNewFileName;
						for (size_t pszlen = 0; pszlen < cbFileNameLen; pszlen++) {
							*p++ = pszFilename[pszlen];
							if (pszFilename[pszlen] == '&')
								*p++ = '&';
						}
						*p = '\0';
						AppendMenu(hMenu, MF_STRING, i + 10, pszNewFileName);
						mir_free(pszNewFileName);
					}
				}
			}

			RECT rc;
			GetWindowRect((HWND)lParam, &rc);
			CheckDlgButton(hwndDlg, IDC_OPENFILE, BST_CHECKED);
			int ret = TrackPopupMenu(hMenu, TPM_RETURNCMD | TPM_RIGHTALIGN, rc.right, rc.bottom, 0, hwndDlg, NULL);
			CheckDlgButton(hwndDlg, IDC_OPENFILE, BST_UNCHECKED);
			DestroyMenu(hMenu);

			if (ret == 1) {
				TCHAR *path = dat->transferStatus.tszWorkingDir;
				if (!path || !path[0]) {
					path = NEWTSTR_ALLOCA(dat->transferStatus.tszCurrentFile);
					TCHAR *p = _tcsrchr(path, '\\');
					if (p)
						*p = 0;
				}

				if (path) ShellExecute(NULL, _T("open"), path, NULL, NULL, SW_SHOW);
			}
			else if (ret && CheckVirusScanned(hwndDlg, dat, ret))
				ShellExecute(NULL, NULL, files[ret - 10], NULL, NULL, SW_SHOW);
		}
		break;
	
	case M_FILEEXISTSDLGREPLY:
		EnableWindow(hwndDlg, TRUE);
		{
			PROTOFILERESUME *pfr = (PROTOFILERESUME*)lParam;
			TCHAR *szOriginalFilename = (TCHAR*)wParam;
			char *szProto = GetContactProto(dat->hContact);

			switch (pfr->action) {
			case FILERESUME_CANCEL:
				if (dat->fs) CallContactService(dat->hContact, PSS_FILECANCEL, (WPARAM)dat->fs, 0);
				dat->fs = NULL;
				mir_free(szOriginalFilename);
				if (pfr->szFilename) mir_free((char*)pfr->szFilename);
				mir_free(pfr);
				return 0;
			case FILERESUME_RESUMEALL:
			case FILERESUME_OVERWRITEALL:
				dat->resumeBehaviour = pfr->action;
				pfr->action &= ~FILERESUMEF_ALL;
				break;
			case FILERESUME_RENAMEALL:
				pfr->action = FILERESUME_RENAME;
				{
					TCHAR *pszExtension, *pszFilename;
					if ((pszFilename = _tcsrchr(szOriginalFilename, '\\')) == NULL) pszFilename = szOriginalFilename;
					if ((pszExtension = _tcsrchr(pszFilename + 1, '.')) == NULL) pszExtension = pszFilename + mir_tstrlen(pszFilename);
					if (pfr->szFilename) mir_free((TCHAR*)pfr->szFilename);
					size_t size = (pszExtension - szOriginalFilename) + 21 + mir_tstrlen(pszExtension);
					pfr->szFilename = (TCHAR*)mir_alloc(sizeof(TCHAR)*size);
					for (int i = 1;; i++) {
						mir_sntprintf((TCHAR*)pfr->szFilename, size, _T("%.*s (%u)%s"), pszExtension - szOriginalFilename, szOriginalFilename, i, pszExtension);
						if (_taccess(pfr->szFilename, 0) != 0)
							break;
					}
				}
				break;
			}
			mir_free(szOriginalFilename);
			CallProtoService(szProto, PS_FILERESUME, (WPARAM)dat->fs, (LPARAM)pfr);
			if (pfr->szFilename) mir_free((char*)pfr->szFilename);
			mir_free(pfr);
		}
		break;

	case HM_RECVEVENT:
		{
			ACKDATA *ack = (ACKDATA*)lParam;
			if (ack->hProcess != dat->fs) break;
			if (ack->type != ACKTYPE_FILE) break;
			if (ack->hContact != dat->hContact) break;

			if (dat->waitingForAcceptance) {
				SetTimer(hwndDlg, 1, 1000, NULL);
				dat->waitingForAcceptance = 0;
			}

			switch (ack->result) {
			case ACKRESULT_SENTREQUEST: SetFtStatus(hwndDlg, LPGENT("Decision sent"), FTS_TEXT); break;
			case ACKRESULT_CONNECTING: SetFtStatus(hwndDlg, LPGENT("Connecting..."), FTS_TEXT); break;
			case ACKRESULT_CONNECTPROXY: SetFtStatus(hwndDlg, LPGENT("Connecting to proxy..."), FTS_TEXT); break;
			case ACKRESULT_CONNECTED: SetFtStatus(hwndDlg, LPGENT("Connected"), FTS_TEXT); break;
			case ACKRESULT_LISTENING: SetFtStatus(hwndDlg, LPGENT("Waiting for connection..."), FTS_TEXT); break;
			case ACKRESULT_INITIALISING: SetFtStatus(hwndDlg, LPGENT("Initializing..."), FTS_TEXT); break;
			case ACKRESULT_NEXTFILE:
				SetFtStatus(hwndDlg, LPGENT("Moving to next file..."), FTS_TEXT);
				SetDlgItemTextA(hwndDlg, IDC_FILENAME, "");
				if (dat->transferStatus.currentFileNumber == 1 && dat->transferStatus.totalFiles > 1 && !dat->send)
					SetOpenFileButtonStyle(GetDlgItem(hwndDlg, IDC_OPENFILE), 1);
				if (dat->transferStatus.currentFileNumber != -1 && dat->files && !dat->send && db_get_b(NULL, "SRFile", "UseScanner", VIRUSSCAN_DISABLE) == VIRUSSCAN_DURINGDL) {
					if (GetFileAttributes(dat->files[dat->transferStatus.currentFileNumber])&FILE_ATTRIBUTE_DIRECTORY)
						PostMessage(hwndDlg, M_VIRUSSCANDONE, dat->transferStatus.currentFileNumber, 0);
					else {
						virusscanthreadstartinfo *vstsi;
						vstsi = (struct virusscanthreadstartinfo*)mir_alloc(sizeof(struct virusscanthreadstartinfo));
						vstsi->hwndReply = hwndDlg;
						vstsi->szFile = mir_tstrdup(dat->files[dat->transferStatus.currentFileNumber]);
						vstsi->returnCode = dat->transferStatus.currentFileNumber;
						forkthread((void(*)(void*))RunVirusScannerThread, 0, vstsi);
					}
				}
				break;

			case ACKRESULT_FILERESUME:
				UpdateProtoFileTransferStatus(&dat->transferStatus, (PROTOFILETRANSFERSTATUS*)ack->lParam);
				{
					PROTOFILETRANSFERSTATUS *fts = &dat->transferStatus;
					SetFilenameControls(hwndDlg, dat, fts);
					if (_taccess(fts->tszCurrentFile, 0))
						break;

					SetFtStatus(hwndDlg, LPGENT("File already exists"), FTS_TEXT);
					if (dat->resumeBehaviour == FILERESUME_ASK) {
						TDlgProcFileExistsParam param = { hwndDlg, fts };
						ShowWindow(hwndDlg, SW_SHOWNORMAL);
						CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_FILEEXISTS), hwndDlg, DlgProcFileExists, (LPARAM)&param);
						EnableWindow(hwndDlg, FALSE);
					}
					else {
						PROTOFILERESUME *pfr = (PROTOFILERESUME*)mir_alloc(sizeof(PROTOFILERESUME));
						pfr->action = dat->resumeBehaviour;
						pfr->szFilename = NULL;
						PostMessage(hwndDlg, M_FILEEXISTSDLGREPLY, (WPARAM)mir_tstrdup(fts->tszCurrentFile), (LPARAM)pfr);
					}
				}
				SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 1);
				return TRUE;

			case ACKRESULT_DATA:
				{
					PROTOFILETRANSFERSTATUS *fts = (PROTOFILETRANSFERSTATUS*)ack->lParam;
					TCHAR str[64], str2[64], szSizeDone[32], szSizeTotal[32];//, *contactName;

					if (dat->fileVirusScanned == NULL)
						dat->fileVirusScanned = (int*)mir_calloc(sizeof(int) * fts->totalFiles);

					// This needs to be here - otherwise we get holes in the files array
					if (!dat->send) {
						if (dat->files == NULL)
							dat->files = (TCHAR**)mir_calloc((fts->totalFiles + 1) * sizeof(TCHAR*));
						if (fts->currentFileNumber < fts->totalFiles && dat->files[fts->currentFileNumber] == NULL)
							dat->files[fts->currentFileNumber] = PFTS_StringToTchar(fts->flags, fts->tszCurrentFile);
					}

					/* HACK: for 0.3.3, limit updates to around 1.1 ack per second */
					if (fts->totalProgress != fts->totalBytes && GetTickCount() < (dat->dwTicks + 650))
						break; // the last update was less than a second ago!
					dat->dwTicks = GetTickCount();

					// Update local transfer status with data from protocol
					UpdateProtoFileTransferStatus(&dat->transferStatus, fts);
					fts = &dat->transferStatus;

					bool firstTime = false;
					if ((GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ALLFILESPROGRESS), GWL_STYLE) & WS_VISIBLE) == 0) {
						SetFtStatus(hwndDlg, (fts->flags & PFTS_SENDING) ? LPGENT("Sending...") : LPGENT("Receiving..."), FTS_PROGRESS);
						SetFilenameControls(hwndDlg, dat, fts);
						firstTime = true;
					}

					const unsigned long lastPos = SendDlgItemMessage(hwndDlg, IDC_ALLFILESPROGRESS, PBM_GETPOS, 0, 0);
					const unsigned long nextPos = fts->totalBytes ? (BIGI(100) * fts->totalProgress / fts->totalBytes) : 0;
					if (lastPos != nextPos || firstTime) {
						SendDlgItemMessage(hwndDlg, IDC_ALLFILESPROGRESS, PBM_SETPOS, nextPos, 0);
						mir_sntprintf(str, _T("%u%%"), nextPos);
						SetDlgItemText(hwndDlg, IDC_ALLPRECENTS, str);
					}

					int units;
					GetSensiblyFormattedSize(fts->totalBytes, szSizeTotal, _countof(szSizeTotal), 0, 1, &units);
					GetSensiblyFormattedSize(fts->totalProgress, szSizeDone, _countof(szSizeDone), units, 0, NULL);
					mir_sntprintf(str, _T("%s/%s"), szSizeDone, szSizeTotal);
					str2[0] = 0;
					GetDlgItemText(hwndDlg, IDC_ALLTRANSFERRED, str2, _countof(str2));
					if (mir_tstrcmp(str, str2))
						SetDlgItemText(hwndDlg, IDC_ALLTRANSFERRED, str);
				}
				break;

			case ACKRESULT_SUCCESS:
			case ACKRESULT_FAILED:
			case ACKRESULT_DENIED:
				HideProgressControls(hwndDlg);
				KillTimer(hwndDlg, 1);
				if (!dat->send)
					SetOpenFileButtonStyle(GetDlgItem(hwndDlg, IDC_OPENFILE), 1);
				SetDlgItemText(hwndDlg, IDCANCEL, TranslateT("Close"));
				if (dat->hNotifyEvent)
					UnhookEvent(dat->hNotifyEvent);
				dat->hNotifyEvent = NULL;

				if (ack->result == ACKRESULT_DENIED) {
					dat->fs = NULL; /* protocol will free structure */
					SkinPlaySound("FileDenied");
					SetFtStatus(hwndDlg, LPGENT("File transfer denied"), FTS_TEXT);
				}
				else if (ack->result == ACKRESULT_FAILED) {
					dat->fs = NULL; /* protocol will free structure */
					SkinPlaySound("FileFailed");
					SetFtStatus(hwndDlg, LPGENT("File transfer failed"), FTS_TEXT);
				}
				else {
					SkinPlaySound("FileDone");
					if (dat->send) {
						dat->fs = NULL; /* protocol will free structure */
						SetFtStatus(hwndDlg, LPGENT("Transfer completed."), FTS_TEXT);

						DBEVENTINFO dbei = { 0 };
						FillSendData(dat, dbei);
						db_event_add(dat->hContact, &dbei);
						if (dbei.pBlob)
							mir_free(dbei.pBlob);
						dat->files = NULL;   //protocol library frees this
					}
					else {
						SetFtStatus(hwndDlg,
							(dat->transferStatus.totalFiles == 1) ?
							LPGENT("Transfer completed, open file.") :
							LPGENT("Transfer completed, open folder."),
							FTS_OPEN);

						int useScanner = db_get_b(NULL, "SRFile", "UseScanner", VIRUSSCAN_DISABLE);
						if (useScanner != VIRUSSCAN_DISABLE) {
							struct virusscanthreadstartinfo *vstsi;
							vstsi = (struct virusscanthreadstartinfo*)mir_alloc(sizeof(struct virusscanthreadstartinfo));
							vstsi->hwndReply = hwndDlg;
							if (useScanner == VIRUSSCAN_DURINGDL) {
								vstsi->returnCode = dat->transferStatus.currentFileNumber;
								if (GetFileAttributes(dat->files[dat->transferStatus.currentFileNumber])&FILE_ATTRIBUTE_DIRECTORY) {
									PostMessage(hwndDlg, M_VIRUSSCANDONE, vstsi->returnCode, 0);
									mir_free(vstsi);
									vstsi = NULL;
								}
								else vstsi->szFile = mir_tstrdup(dat->files[dat->transferStatus.currentFileNumber]);
							}
							else {
								vstsi->szFile = mir_tstrdup(dat->transferStatus.tszWorkingDir);
								vstsi->returnCode = -1;
							}
							SetFtStatus(hwndDlg, LPGENT("Scanning for viruses..."), FTS_TEXT);
							if (vstsi)
								forkthread((void(*)(void*))RunVirusScannerThread, 0, vstsi);
						}
						else dat->fs = NULL; /* protocol will free structure */

						dat->transferStatus.currentFileNumber = dat->transferStatus.totalFiles;
					} // else dat->send

				} // else ack->result

				PostMessage(GetParent(hwndDlg), WM_FT_COMPLETED, ack->result, (LPARAM)hwndDlg);
				break;
			} // switch ack->result
		} // case HM_RECVEVENT
		break; 

	case M_VIRUSSCANDONE:
		{
			int done = 1;
			if ((int)wParam == -1) {
				for (int i = 0; i < dat->transferStatus.totalFiles; i++)
					dat->fileVirusScanned[i] = 1;
			}
			else {
				dat->fileVirusScanned[wParam] = 1;
				for (int i = 0; i < dat->transferStatus.totalFiles; i++) 
					if (!dat->fileVirusScanned[i]) {
						done = 0;
						break;
					}
			}
			if (done) {
				dat->fs = NULL; /* protocol will free structure */
				SetFtStatus(hwndDlg, LPGENT("Transfer and virus scan complete"), FTS_TEXT);
			}
		}
		break;

	case WM_SIZE:
		Utils_ResizeDialog(hwndDlg, hInst, MAKEINTRESOURCEA(IDD_FILETRANSFERINFO), FileTransferDlgResizer);

		RedrawWindow(GetDlgItem(hwndDlg, IDC_ALLTRANSFERRED), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE);
		RedrawWindow(GetDlgItem(hwndDlg, IDC_ALLSPEED), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE);
		RedrawWindow(GetDlgItem(hwndDlg, IDC_CONTACTNAME), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE);
		RedrawWindow(GetDlgItem(hwndDlg, IDC_STATUS), NULL, NULL, RDW_INVALIDATE | RDW_NOERASE);
		break;

	case WM_DESTROY:
		KillTimer(hwndDlg, 1);

		HFONT hFont = (HFONT)SendDlgItemMessage(hwndDlg, IDC_CONTACTNAME, WM_GETFONT, 0, 0);
		DeleteObject(hFont);

		Button_FreeIcon_IcoLib(hwndDlg, IDC_CONTACT);
		Button_FreeIcon_IcoLib(hwndDlg, IDC_OPENFILE);
		Button_FreeIcon_IcoLib(hwndDlg, IDCANCEL);

		FreeFileDlgData(dat);
		SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
		break;
	}
	return FALSE;
}
예제 #3
0
INT_PTR CALLBACK DlgProcSendFile(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	struct FileDlgData *dat;

	dat=(struct FileDlgData*)GetWindowLongPtr(hwndDlg,GWLP_USERDATA);
	switch (msg) {
	case WM_INITDIALOG:
	{
		struct FileSendData *fsd=(struct FileSendData*)lParam;

		dat=(struct FileDlgData*)mir_calloc(sizeof(struct FileDlgData));
		SetWindowLongPtr(hwndDlg,GWLP_USERDATA,(LONG_PTR)dat);
		dat->hContact=fsd->hContact;
		dat->send=1;
		dat->hPreshutdownEvent=HookEventMessage(ME_SYSTEM_PRESHUTDOWN,hwndDlg,M_PRESHUTDOWN);
		dat->fs=NULL;
		dat->dwTicks=GetTickCount();

		TranslateDialogDefault(hwndDlg);
		EnumChildWindows(hwndDlg,ClipSiblingsChildEnumProc,0);
		OldSendEditProc=(WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_MSG),GWLP_WNDPROC,(LONG_PTR)SendEditSubclassProc);

		Window_SetIcon_IcoLib(hwndDlg, SKINICON_EVENT_FILE);
		Button_SetIcon_IcoLib(hwndDlg, IDC_DETAILS, SKINICON_OTHER_USERDETAILS, LPGEN("View User's Details"));
		Button_SetIcon_IcoLib(hwndDlg, IDC_HISTORY, SKINICON_OTHER_HISTORY, LPGEN("View User's History"));
		Button_SetIcon_IcoLib(hwndDlg, IDC_USERMENU, SKINICON_OTHER_DOWNARROW, LPGEN("User Menu"));

        EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);

		if(fsd->ppFiles!=NULL && fsd->ppFiles[0]!=NULL) {
			int totalCount,i;
			for(totalCount=0;fsd->ppFiles[totalCount];totalCount++);
			dat->files = ( TCHAR** )mir_alloc( sizeof(TCHAR*)*(totalCount+1)); // Leaks
			for(i=0;i<totalCount;i++)
				dat->files[i] = mir_tstrdup( fsd->ppFiles[i] );
			dat->files[totalCount]=NULL;
			SetFileListAndSizeControls(hwndDlg,dat);
		}
		{
			char *szProto;
			TCHAR* contactName = cli.pfnGetContactDisplayName( dat->hContact, 0 );
			SetDlgItemText(hwndDlg,IDC_TO,contactName);

			szProto=(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)dat->hContact,0);
			if (szProto) {
				CONTACTINFO ci;
				int hasName = 0;
				char buf[128];
				ZeroMemory(&ci,sizeof(ci));

				ci.cbSize = sizeof(ci);
				ci.hContact = dat->hContact;
				ci.szProto = szProto;
				ci.dwFlag = CNF_UNIQUEID;
				if (!CallService(MS_CONTACT_GETCONTACTINFO,0,(LPARAM)&ci)) {
					switch(ci.type) {
						case CNFT_ASCIIZ:
							hasName = 1;
							mir_snprintf(buf, SIZEOF(buf), "%s", ci.pszVal);
							mir_free(ci.pszVal);
							break;
						case CNFT_DWORD:
							hasName = 1;
							mir_snprintf(buf, SIZEOF(buf),"%u",ci.dVal);
							break;
				}	}

				if ( hasName )
					SetDlgItemTextA(hwndDlg,IDC_NAME,buf);
				else
					SetDlgItemText(hwndDlg,IDC_NAME,contactName);
		}	}

		if ( fsd->ppFiles == NULL ) {
       		EnableWindow(hwndDlg, FALSE);
			dat->closeIfFileChooseCancelled=1;
			PostMessage(hwndDlg,WM_COMMAND,MAKEWPARAM(IDC_CHOOSE,BN_CLICKED),(LPARAM)GetDlgItem(hwndDlg,IDC_CHOOSE));
		}
		return TRUE;
	}

	case WM_MEASUREITEM:
		return CallService(MS_CLIST_MENUMEASUREITEM,wParam,lParam);

	case WM_DRAWITEM:
		{
			LPDRAWITEMSTRUCT dis=(LPDRAWITEMSTRUCT)lParam;
			if(dis->hwndItem==GetDlgItem(hwndDlg, IDC_PROTOCOL)) {
				char *szProto;

				szProto=(char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)dat->hContact,0);
				if (szProto) {
					HICON hIcon = (HICON)CallProtoService(szProto,PS_LOADICON,PLI_PROTOCOL|PLIF_SMALL,0);
					if (hIcon) {
						DrawIconEx(dis->hDC,dis->rcItem.left,dis->rcItem.top,hIcon,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL);
						DestroyIcon(hIcon);
		}	}	}	}
		return CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam);
		
	case M_FILECHOOSEDONE:
		if( lParam != 0 ) {
			FilenameToFileList( hwndDlg, dat, ( TCHAR* )lParam );
			mir_free(( TCHAR* )lParam );
			dat->closeIfFileChooseCancelled = 0;
		}
		else if(dat->closeIfFileChooseCancelled) DestroyWindow(hwndDlg);
		EnableWindow(hwndDlg,TRUE);
		break;

	case WM_COMMAND:
		if(CallService(MS_CLIST_MENUPROCESSCOMMAND,MAKEWPARAM(LOWORD(wParam),MPCF_CONTACTMENU),(LPARAM)dat->hContact))
			break;
		switch (LOWORD(wParam))
		{
			case IDC_CHOOSE:
				EnableWindow(hwndDlg,FALSE);
				//GetOpenFileName() creates its own message queue which prevents any incoming events being processed
				forkthread(ChooseFilesThread,0,hwndDlg);
				break;
			case IDOK:
				EnableWindow(GetDlgItem(hwndDlg,IDC_FILENAME),FALSE);
				EnableWindow(GetDlgItem(hwndDlg,IDC_MSG),FALSE);
				EnableWindow(GetDlgItem(hwndDlg,IDC_CHOOSE),FALSE);

				GetDlgItemText(hwndDlg,IDC_FILEDIR,dat->szSavePath,SIZEOF(dat->szSavePath));
				GetDlgItemText(hwndDlg,IDC_FILE,dat->szFilenames,SIZEOF(dat->szFilenames));
				GetDlgItemText(hwndDlg,IDC_MSG,dat->szMsg,SIZEOF(dat->szMsg));
				dat->hwndTransfer = FtMgr_AddTransfer(dat);
				SetWindowLongPtr( hwndDlg, GWLP_USERDATA, 0);
				DestroyWindow(hwndDlg);
				return TRUE;

			case IDCANCEL:
				DestroyWindow(hwndDlg);
				return TRUE;

			case IDC_USERMENU:
			{	RECT rc;
				HMENU hMenu=(HMENU)CallService(MS_CLIST_MENUBUILDCONTACT,(WPARAM)dat->hContact,0);
				GetWindowRect((HWND)lParam,&rc);
				TrackPopupMenu(hMenu,0,rc.left,rc.bottom,0,hwndDlg,NULL);
				DestroyMenu(hMenu);
				break;
			}
			case IDC_DETAILS:
				CallService(MS_USERINFO_SHOWDIALOG,(WPARAM)dat->hContact,0);
				return TRUE;
			case IDC_HISTORY:
				CallService(MS_HISTORY_SHOWCONTACTHISTORY,(WPARAM)dat->hContact,0);
				return TRUE;
		}
		break;

	case WM_DESTROY:
		Window_FreeIcon_IcoLib(hwndDlg);
		Button_FreeIcon_IcoLib(hwndDlg,IDC_DETAILS);
		Button_FreeIcon_IcoLib(hwndDlg,IDC_HISTORY);
		Button_FreeIcon_IcoLib(hwndDlg,IDC_USERMENU);

		if ( dat )
			FreeFileDlgData( dat );
		
		SetWindowLongPtr(GetDlgItem(hwndDlg,IDC_MSG),GWLP_WNDPROC,(LONG_PTR)OldSendEditProc);
		return TRUE;
	}
	return FALSE;
}
예제 #4
0
INT_PTR CALLBACK DlgProcSendFile(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	FileDlgData *dat = (FileDlgData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
	switch (msg) {
	case WM_INITDIALOG:
		TranslateDialogDefault(hwndDlg);
		{
			struct FileSendData *fsd = (struct FileSendData*)lParam;

			dat = (FileDlgData*)mir_calloc(sizeof(FileDlgData));
			SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat);
			dat->hContact = fsd->hContact;
			dat->send = 1;
			dat->hPreshutdownEvent = HookEventMessage(ME_SYSTEM_PRESHUTDOWN, hwndDlg, M_PRESHUTDOWN);
			dat->fs = NULL;
			dat->dwTicks = GetTickCount();

			EnumChildWindows(hwndDlg, ClipSiblingsChildEnumProc, 0);
			mir_subclassWindow(GetDlgItem(hwndDlg, IDC_MSG), SendEditSubclassProc);

			Window_SetSkinIcon_IcoLib(hwndDlg, SKINICON_EVENT_FILE);
			Button_SetIcon_IcoLib(hwndDlg, IDC_DETAILS, SKINICON_OTHER_USERDETAILS, LPGEN("View user's details"));
			Button_SetIcon_IcoLib(hwndDlg, IDC_HISTORY, SKINICON_OTHER_HISTORY, LPGEN("View user's history"));
			Button_SetIcon_IcoLib(hwndDlg, IDC_USERMENU, SKINICON_OTHER_DOWNARROW, LPGEN("User menu"));

			EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);

			if (fsd->ppFiles != NULL && fsd->ppFiles[0] != NULL) {
				int totalCount, i;
				for (totalCount = 0; fsd->ppFiles[totalCount]; totalCount++);
				dat->files = (TCHAR**)mir_alloc(sizeof(TCHAR*)*(totalCount + 1)); // Leaks
				for (i = 0; i < totalCount; i++)
					dat->files[i] = mir_tstrdup(fsd->ppFiles[i]);
				dat->files[totalCount] = NULL;
				SetFileListAndSizeControls(hwndDlg, dat);
			}

			TCHAR *contactName = pcli->pfnGetContactDisplayName(dat->hContact, 0);
			SetDlgItemText(hwndDlg, IDC_TO, contactName);

			ptrT id(Contact_GetInfo(CNF_UNIQUEID, dat->hContact));
			SetDlgItemText(hwndDlg, IDC_NAME, (id) ? id : contactName);

			if (fsd->ppFiles == NULL) {
				EnableWindow(hwndDlg, FALSE);
				dat->closeIfFileChooseCancelled = 1;
				PostMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_CHOOSE, BN_CLICKED), (LPARAM)GetDlgItem(hwndDlg, IDC_CHOOSE));
			}
		}
		return TRUE;

	case WM_MEASUREITEM:
		return Menu_MeasureItem((LPMEASUREITEMSTRUCT)lParam);

	case WM_DRAWITEM:
		{
			LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lParam;
			if (dis->hwndItem == GetDlgItem(hwndDlg, IDC_PROTOCOL)) {
				char *szProto = GetContactProto(dat->hContact);
				if (szProto) {
					HICON hIcon = (HICON)CallProtoService(szProto, PS_LOADICON, PLI_PROTOCOL | PLIF_SMALL, 0);
					if (hIcon) {
						DrawIconEx(dis->hDC, dis->rcItem.left, dis->rcItem.top, hIcon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0, NULL, DI_NORMAL);
						DestroyIcon(hIcon);
					}
				}
			}
		}
		return Menu_DrawItem((LPDRAWITEMSTRUCT)lParam);

	case M_FILECHOOSEDONE:
		if (lParam != 0) {
			FilenameToFileList(hwndDlg, dat, (TCHAR*)lParam);
			mir_free((TCHAR*)lParam);
			dat->closeIfFileChooseCancelled = 0;
		}
		else if (dat->closeIfFileChooseCancelled)
			PostMessage(hwndDlg, WM_COMMAND, IDCANCEL, 0);

		EnableWindow(hwndDlg, TRUE);
		break;

	case WM_COMMAND:
		if (CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM)dat->hContact))
			break;

		switch (LOWORD(wParam)) {
		case IDC_CHOOSE:
			EnableWindow(hwndDlg, FALSE);
			mir_forkthread(ChooseFilesThread, hwndDlg);
			break;

		case IDOK:
			NotifyEventHooks(hDlgSucceeded, dat->hContact, (LPARAM)hwndDlg);

			EnableWindow(GetDlgItem(hwndDlg, IDC_FILENAME), FALSE);
			EnableWindow(GetDlgItem(hwndDlg, IDC_MSG), FALSE);
			EnableWindow(GetDlgItem(hwndDlg, IDC_CHOOSE), FALSE);

			GetDlgItemText(hwndDlg, IDC_FILEDIR, dat->szSavePath, _countof(dat->szSavePath));
			GetDlgItemText(hwndDlg, IDC_FILE, dat->szFilenames, _countof(dat->szFilenames));
			GetDlgItemText(hwndDlg, IDC_MSG, dat->szMsg, _countof(dat->szMsg));
			dat->hwndTransfer = FtMgr_AddTransfer(dat);
			SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
			DestroyWindow(hwndDlg);
			return TRUE;

		case IDCANCEL:
			NotifyEventHooks(hDlgCanceled, dat->hContact, (LPARAM)hwndDlg);
			DestroyWindow(hwndDlg);
			return TRUE;

		case IDC_USERMENU:
			{
				RECT rc;
				GetWindowRect((HWND)lParam, &rc);
				HMENU hMenu = Menu_BuildContactMenu(dat->hContact);
				TrackPopupMenu(hMenu, 0, rc.left, rc.bottom, 0, hwndDlg, NULL);
				DestroyMenu(hMenu);
			}
			break;

		case IDC_DETAILS:
			CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)dat->hContact, 0);
			return TRUE;

		case IDC_HISTORY:
			CallService(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM)dat->hContact, 0);
			return TRUE;
		}
		break;

	case WM_DESTROY:
		Window_FreeIcon_IcoLib(hwndDlg);
		Button_FreeIcon_IcoLib(hwndDlg, IDC_DETAILS);
		Button_FreeIcon_IcoLib(hwndDlg, IDC_HISTORY);
		Button_FreeIcon_IcoLib(hwndDlg, IDC_USERMENU);

		FreeFileDlgData(dat);
		SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
		return TRUE;
	}
	return FALSE;
}