started signal handlers, shadow fixed in sticker-by-emoji, via @bot resize fixed

This commit is contained in:
John Preston 2016-01-10 14:05:23 +08:00
parent 5531f49c3e
commit 71f588a4fe
18 changed files with 253 additions and 202 deletions

View File

@ -333,9 +333,8 @@ void updateRegistry() {
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdParamarg, int cmdShow) { int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdParamarg, int cmdShow) {
openLog(); openLog();
#ifdef _NEED_WIN_GENERATE_DUMP
_oldWndExceptionFilter = SetUnhandledExceptionFilter(_exceptionFilter); _oldWndExceptionFilter = SetUnhandledExceptionFilter(_exceptionFilter);
#endif // CAPIHook apiHook("kernel32.dll", "SetUnhandledExceptionFilter", (PROC)RedirectedSetUnhandledExceptionFilter);
writeLog(L"Updaters started.."); writeLog(L"Updaters started..");
@ -465,7 +464,6 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdPara
return 0; return 0;
} }
#ifdef _NEED_WIN_GENERATE_DUMP
static const WCHAR *_programName = L"Telegram Desktop"; // folder in APPDATA, if current path is unavailable for writing static const WCHAR *_programName = L"Telegram Desktop"; // folder in APPDATA, if current path is unavailable for writing
static const WCHAR *_exeName = L"Updater.exe"; static const WCHAR *_exeName = L"Updater.exe";
@ -507,10 +505,10 @@ HANDLE _generateDumpFileAtPath(const WCHAR *path) {
GetLocalTime(&stLocalTime); GetLocalTime(&stLocalTime);
wsprintf(szFileName, L"%s%s-%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp", wsprintf(szFileName, L"%s%s-%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",
szPath, szExeName, updaterVersionStr, szPath, szExeName, updaterVersionStr,
stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond,
GetCurrentProcessId(), GetCurrentThreadId()); GetCurrentProcessId(), GetCurrentThreadId());
return CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0); return CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
} }
@ -546,7 +544,7 @@ void _generateDump(EXCEPTION_POINTERS* pExceptionPointers) {
hDumpFile = _generateDumpFileAtPath(wstrPath); hDumpFile = _generateDumpFileAtPath(wstrPath);
} }
} }
if (!hDumpFile || hDumpFile == INVALID_HANDLE_VALUE) { if (!hDumpFile || hDumpFile == INVALID_HANDLE_VALUE) {
return; return;
} }
@ -564,4 +562,10 @@ LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers) {
return _oldWndExceptionFilter ? (*_oldWndExceptionFilter)(pExceptionPointers) : EXCEPTION_CONTINUE_SEARCH; return _oldWndExceptionFilter ? (*_oldWndExceptionFilter)(pExceptionPointers) : EXCEPTION_CONTINUE_SEARCH;
} }
#endif // see http://www.codeproject.com/Articles/154686/SetUnhandledExceptionFilter-and-the-C-C-Runtime-Li
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI RedirectedSetUnhandledExceptionFilter(_In_opt_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) {
// When the CRT calls SetUnhandledExceptionFilter with NULL parameter
// our handler will not get removed.
_oldWndExceptionFilter = lpTopLevelExceptionFilter;
return 0;
}

View File

@ -32,12 +32,9 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
using std::deque; using std::deque;
using std::wstring; using std::wstring;
#define _NEED_WIN_GENERATE_DUMP
#ifdef _NEED_WIN_GENERATE_DUMP
extern LPTOP_LEVEL_EXCEPTION_FILTER _oldWndExceptionFilter; extern LPTOP_LEVEL_EXCEPTION_FILTER _oldWndExceptionFilter;
LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers); LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers);
#endif _NEED_WIN_GENERATE_DUMP LPTOP_LEVEL_EXCEPTION_FILTER WINAPI RedirectedSetUnhandledExceptionFilter(_In_opt_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);
static int updaterVersion = 1000; static int updaterVersion = 1000;
static const WCHAR *updaterVersionStr = L"0.1.0"; static const WCHAR *updaterVersionStr = L"0.1.0";

View File

@ -935,7 +935,7 @@ namespace App {
} }
void checkSavedGif(HistoryItem *item) { void checkSavedGif(HistoryItem *item) {
if (!item->toHistoryForwarded() && item->out()) { if (!item->toHistoryForwarded() && (item->out() || item->history()->peer == App::self())) {
if (HistoryMedia *media = item->getMedia()) { if (HistoryMedia *media = item->getMedia()) {
if (DocumentData *doc = media->getDocument()) { if (DocumentData *doc = media->getDocument()) {
if (doc->isGifv()) { if (doc->isGifv()) {

View File

@ -208,7 +208,7 @@ void Application::updateGotCurrent() {
if (!updateReply || updateThread) return; if (!updateReply || updateThread) return;
cSetLastUpdateCheck(unixtime()); cSetLastUpdateCheck(unixtime());
QRegularExpressionMatch m = QRegularExpression(qsl("^\\s*(\\d+)\\s*:\\s*([\\x21-\\x7f]+)\\s*$")).match(QString::fromUtf8(updateReply->readAll())); QRegularExpressionMatch m = QRegularExpression(qsl("^\\s*(\\d+)\\s*:\\s*([\\x21-\\x7f]+)\\s*$")).match(QString::fromLatin1(updateReply->readAll()));
if (m.hasMatch()) { if (m.hasMatch()) {
uint64 currentVersion = m.captured(1).toULongLong(); uint64 currentVersion = m.captured(1).toULongLong();
QString url = m.captured(2); QString url = m.captured(2);
@ -642,7 +642,7 @@ void Application::socketConnected() {
} }
commands += qsl("CMD:show;"); commands += qsl("CMD:show;");
DEBUG_LOG(("Application Info: writing commands %1").arg(commands)); DEBUG_LOG(("Application Info: writing commands %1").arg(commands));
socket.write(commands.toLocal8Bit()); socket.write(commands.toLatin1());
} }
void Application::socketWritten(qint64/* bytes*/) { void Application::socketWritten(qint64/* bytes*/) {
@ -799,13 +799,13 @@ void Application::readClients() {
for (ClientSockets::iterator i = clients.begin(), e = clients.end(); i != e; ++i) { for (ClientSockets::iterator i = clients.begin(), e = clients.end(); i != e; ++i) {
i->second.append(i->first->readAll()); i->second.append(i->first->readAll());
if (i->second.size()) { if (i->second.size()) {
QString cmds(QString::fromLocal8Bit(i->second)); QString cmds(QString::fromLatin1(i->second));
int32 from = 0, l = cmds.length(); int32 from = 0, l = cmds.length();
for (int32 to = cmds.indexOf(QChar(';'), from); to >= from; to = (from < l) ? cmds.indexOf(QChar(';'), from) : -1) { for (int32 to = cmds.indexOf(QChar(';'), from); to >= from; to = (from < l) ? cmds.indexOf(QChar(';'), from) : -1) {
QStringRef cmd(&cmds, from, to - from); QStringRef cmd(&cmds, from, to - from);
if (cmd.startsWith(qsl("CMD:"))) { if (cmd.startsWith(qsl("CMD:"))) {
execExternal(cmds.mid(from + 4, to - from - 4)); execExternal(cmds.mid(from + 4, to - from - 4));
QByteArray response(qsl("RES:%1;").arg(QCoreApplication::applicationPid()).toUtf8()); QByteArray response(qsl("RES:%1;").arg(QCoreApplication::applicationPid()).toLatin1());
i->first->write(response.data(), response.size()); i->first->write(response.data(), response.size());
} else if (cmd.startsWith(qsl("SEND:"))) { } else if (cmd.startsWith(qsl("SEND:"))) {
if (cSendPaths().isEmpty()) { if (cSendPaths().isEmpty()) {

View File

@ -3906,122 +3906,120 @@ void MentionsInner::paintEvent(QPaintEvent *e) {
} }
} }
} }
return; } else {
} int32 from = qFloor(e->rect().top() / st::mentionHeight), to = qFloor(e->rect().bottom() / st::mentionHeight) + 1;
int32 last = _mrows->isEmpty() ? (_hrows->isEmpty() ? _brows->size() : _hrows->size()) : _mrows->size();
bool hasUsername = _parent->filter().indexOf('@') > 1;
for (int32 i = from; i < to; ++i) {
if (i >= last) break;
int32 from = qFloor(e->rect().top() / st::mentionHeight), to = qFloor(e->rect().bottom() / st::mentionHeight) + 1; bool selected = (i == _sel);
int32 last = _mrows->isEmpty() ? (_hrows->isEmpty() ? _brows->size() : _hrows->size()) : _mrows->size(); if (selected) {
bool hasUsername = _parent->filter().indexOf('@') > 1; p.fillRect(0, i * st::mentionHeight, width(), st::mentionHeight, st::mentionBgOver->b);
for (int32 i = from; i < to; ++i) { int skip = (st::mentionHeight - st::notifyClose.icon.pxHeight()) / 2;
if (i >= last) break; if (!_hrows->isEmpty() || (!_mrows->isEmpty() && i < _recentInlineBotsInRows)) p.drawPixmap(QPoint(width() - st::notifyClose.icon.pxWidth() - skip, i * st::mentionHeight + skip), App::sprite(), st::notifyClose.icon);
}
bool selected = (i == _sel); p.setPen(st::black->p);
if (selected) { if (!_mrows->isEmpty()) {
p.fillRect(0, i * st::mentionHeight, width(), st::mentionHeight, st::mentionBgOver->b); UserData *user = _mrows->at(i);
int skip = (st::mentionHeight - st::notifyClose.icon.pxHeight()) / 2; QString first = (_parent->filter().size() < 2) ? QString() : ('@' + user->username.mid(0, _parent->filter().size() - 1)), second = (_parent->filter().size() < 2) ? ('@' + user->username) : user->username.mid(_parent->filter().size() - 1);
if (!_hrows->isEmpty() || (!_mrows->isEmpty() && i < _recentInlineBotsInRows)) p.drawPixmap(QPoint(width() - st::notifyClose.icon.pxWidth() - skip, i * st::mentionHeight + skip), App::sprite(), st::notifyClose.icon); int32 firstwidth = st::mentionFont->width(first), secondwidth = st::mentionFont->width(second), unamewidth = firstwidth + secondwidth, namewidth = user->nameText.maxWidth();
} if (mentionwidth < unamewidth + namewidth) {
p.setPen(st::black->p); namewidth = (mentionwidth * namewidth) / (namewidth + unamewidth);
if (!_mrows->isEmpty()) { unamewidth = mentionwidth - namewidth;
UserData *user = _mrows->at(i); if (firstwidth < unamewidth + st::mentionFont->elidew) {
QString first = (_parent->filter().size() < 2) ? QString() : ('@' + user->username.mid(0, _parent->filter().size() - 1)), second = (_parent->filter().size() < 2) ? ('@' + user->username) : user->username.mid(_parent->filter().size() - 1); if (firstwidth < unamewidth) {
int32 firstwidth = st::mentionFont->width(first), secondwidth = st::mentionFont->width(second), unamewidth = firstwidth + secondwidth, namewidth = user->nameText.maxWidth(); first = st::mentionFont->elided(first, unamewidth);
if (mentionwidth < unamewidth + namewidth) { } else if (!second.isEmpty()) {
namewidth = (mentionwidth * namewidth) / (namewidth + unamewidth); first = st::mentionFont->elided(first + second, unamewidth);
unamewidth = mentionwidth - namewidth; second = QString();
if (firstwidth < unamewidth + st::mentionFont->elidew) { }
if (firstwidth < unamewidth) { } else {
first = st::mentionFont->elided(first, unamewidth); second = st::mentionFont->elided(second, unamewidth - firstwidth);
} else if (!second.isEmpty()) {
first = st::mentionFont->elided(first + second, unamewidth);
second = QString();
} }
} else {
second = st::mentionFont->elided(second, unamewidth - firstwidth);
} }
}
user->photo->load();
p.drawPixmap(st::mentionPadding.left(), i * st::mentionHeight + st::mentionPadding.top(), user->photo->pixRounded(st::mentionPhotoSize));
user->nameText.drawElided(p, 2 * st::mentionPadding.left() + st::mentionPhotoSize, i * st::mentionHeight + st::mentionTop, namewidth);
p.setFont(st::mentionFont->f);
p.setPen((selected ? st::mentionFgOverActive : st::mentionFgActive)->p);
p.drawText(mentionleft + namewidth + st::mentionPadding.right(), i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, first);
if (!second.isEmpty()) {
p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p);
p.drawText(mentionleft + namewidth + st::mentionPadding.right() + firstwidth, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, second);
}
} else if (!_hrows->isEmpty()) {
QString hrow = _hrows->at(i);
QString first = (_parent->filter().size() < 2) ? QString() : ('#' + hrow.mid(0, _parent->filter().size() - 1)), second = (_parent->filter().size() < 2) ? ('#' + hrow) : hrow.mid(_parent->filter().size() - 1);
int32 firstwidth = st::mentionFont->width(first), secondwidth = st::mentionFont->width(second);
if (htagwidth < firstwidth + secondwidth) {
if (htagwidth < firstwidth + st::mentionFont->elidew) {
first = st::mentionFont->elided(first + second, htagwidth);
second = QString();
} else {
second = st::mentionFont->elided(second, htagwidth - firstwidth);
}
}
p.setFont(st::mentionFont->f);
if (!first.isEmpty()) {
p.setPen((selected ? st::mentionFgOverActive : st::mentionFgActive)->p);
p.drawText(htagleft, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, first);
}
if (!second.isEmpty()) {
p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p);
p.drawText(htagleft + firstwidth, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, second);
}
} else {
UserData *user = _brows->at(i).first;
const BotCommand *command = _brows->at(i).second;
QString toHighlight = command->command;
int32 botStatus = _parent->chat() ? _parent->chat()->botStatus : ((_parent->channel() && _parent->channel()->isMegagroup()) ? _parent->channel()->mgInfo->botStatus : -1);
if (hasUsername || botStatus == 0 || botStatus == 2) {
toHighlight += '@' + user->username;
}
if (true || _parent->chat() || botStatus == 0 || botStatus == 2) {
user->photo->load(); user->photo->load();
p.drawPixmap(st::mentionPadding.left(), i * st::mentionHeight + st::mentionPadding.top(), user->photo->pixRounded(st::mentionPhotoSize)); p.drawPixmap(st::mentionPadding.left(), i * st::mentionHeight + st::mentionPadding.top(), user->photo->pixRounded(st::mentionPhotoSize));
} user->nameText.drawElided(p, 2 * st::mentionPadding.left() + st::mentionPhotoSize, i * st::mentionHeight + st::mentionTop, namewidth);
int32 addleft = 0, widthleft = mentionwidth; p.setFont(st::mentionFont->f);
QString first = (_parent->filter().size() < 2) ? QString() : ('/' + toHighlight.mid(0, _parent->filter().size() - 1)), second = (_parent->filter().size() < 2) ? ('/' + toHighlight) : toHighlight.mid(_parent->filter().size() - 1); p.setPen((selected ? st::mentionFgOverActive : st::mentionFgActive)->p);
int32 firstwidth = st::mentionFont->width(first), secondwidth = st::mentionFont->width(second); p.drawText(mentionleft + namewidth + st::mentionPadding.right(), i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, first);
if (widthleft < firstwidth + secondwidth) { if (!second.isEmpty()) {
if (widthleft < firstwidth + st::mentionFont->elidew) { p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p);
first = st::mentionFont->elided(first + second, widthleft); p.drawText(mentionleft + namewidth + st::mentionPadding.right() + firstwidth, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, second);
second = QString(); }
} else { } else if (!_hrows->isEmpty()) {
second = st::mentionFont->elided(second, widthleft - firstwidth); QString hrow = _hrows->at(i);
QString first = (_parent->filter().size() < 2) ? QString() : ('#' + hrow.mid(0, _parent->filter().size() - 1)), second = (_parent->filter().size() < 2) ? ('#' + hrow) : hrow.mid(_parent->filter().size() - 1);
int32 firstwidth = st::mentionFont->width(first), secondwidth = st::mentionFont->width(second);
if (htagwidth < firstwidth + secondwidth) {
if (htagwidth < firstwidth + st::mentionFont->elidew) {
first = st::mentionFont->elided(first + second, htagwidth);
second = QString();
} else {
second = st::mentionFont->elided(second, htagwidth - firstwidth);
}
}
p.setFont(st::mentionFont->f);
if (!first.isEmpty()) {
p.setPen((selected ? st::mentionFgOverActive : st::mentionFgActive)->p);
p.drawText(htagleft, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, first);
}
if (!second.isEmpty()) {
p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p);
p.drawText(htagleft + firstwidth, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, second);
}
} else {
UserData *user = _brows->at(i).first;
const BotCommand *command = _brows->at(i).second;
QString toHighlight = command->command;
int32 botStatus = _parent->chat() ? _parent->chat()->botStatus : ((_parent->channel() && _parent->channel()->isMegagroup()) ? _parent->channel()->mgInfo->botStatus : -1);
if (hasUsername || botStatus == 0 || botStatus == 2) {
toHighlight += '@' + user->username;
}
if (true || _parent->chat() || botStatus == 0 || botStatus == 2) {
user->photo->load();
p.drawPixmap(st::mentionPadding.left(), i * st::mentionHeight + st::mentionPadding.top(), user->photo->pixRounded(st::mentionPhotoSize));
}
int32 addleft = 0, widthleft = mentionwidth;
QString first = (_parent->filter().size() < 2) ? QString() : ('/' + toHighlight.mid(0, _parent->filter().size() - 1)), second = (_parent->filter().size() < 2) ? ('/' + toHighlight) : toHighlight.mid(_parent->filter().size() - 1);
int32 firstwidth = st::mentionFont->width(first), secondwidth = st::mentionFont->width(second);
if (widthleft < firstwidth + secondwidth) {
if (widthleft < firstwidth + st::mentionFont->elidew) {
first = st::mentionFont->elided(first + second, widthleft);
second = QString();
} else {
second = st::mentionFont->elided(second, widthleft - firstwidth);
}
}
p.setFont(st::mentionFont->f);
if (!first.isEmpty()) {
p.setPen((selected ? st::mentionFgOverActive : st::mentionFgActive)->p);
p.drawText(mentionleft, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, first);
}
if (!second.isEmpty()) {
p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p);
p.drawText(mentionleft + firstwidth, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, second);
}
addleft += firstwidth + secondwidth + st::mentionPadding.left();
widthleft -= firstwidth + secondwidth + st::mentionPadding.left();
if (widthleft > st::mentionFont->elidew && !command->descriptionText().isEmpty()) {
p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p);
command->descriptionText().drawElided(p, mentionleft + addleft, i * st::mentionHeight + st::mentionTop, widthleft, 1, style::al_right);
} }
} }
p.setFont(st::mentionFont->f);
if (!first.isEmpty()) {
p.setPen((selected ? st::mentionFgOverActive : st::mentionFgActive)->p);
p.drawText(mentionleft, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, first);
}
if (!second.isEmpty()) {
p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p);
p.drawText(mentionleft + firstwidth, i * st::mentionHeight + st::mentionTop + st::mentionFont->ascent, second);
}
addleft += firstwidth + secondwidth + st::mentionPadding.left();
widthleft -= firstwidth + secondwidth + st::mentionPadding.left();
if (widthleft > st::mentionFont->elidew && !command->descriptionText().isEmpty()) {
p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p);
command->descriptionText().drawElided(p, mentionleft + addleft, i * st::mentionHeight + st::mentionTop, widthleft, 1, style::al_right);
}
} }
p.fillRect(cWideMode() ? st::lineWidth : 0, _parent->innerBottom() - st::lineWidth, width() - (cWideMode() ? st::lineWidth : 0), st::lineWidth, st::shadowColor->b);
} }
p.fillRect(cWideMode() ? st::lineWidth : 0, _parent->innerTop(), width() - (cWideMode() ? st::lineWidth : 0), st::lineWidth, st::shadowColor->b); p.fillRect(cWideMode() ? st::lineWidth : 0, _parent->innerTop(), width() - (cWideMode() ? st::lineWidth : 0), st::lineWidth, st::shadowColor->b);
p.fillRect(cWideMode() ? st::lineWidth : 0, _parent->innerBottom() - st::lineWidth, width() - (cWideMode() ? st::lineWidth : 0), st::lineWidth, st::shadowColor->b);
} }
void MentionsInner::resizeEvent(QResizeEvent *e) { void MentionsInner::resizeEvent(QResizeEvent *e) {
_stickersPerRow = int32(width() - 2 * st::stickerPanPadding) / int32(st::stickerPanSize.width()); _stickersPerRow = qMax(1, int32(width() - 2 * st::stickerPanPadding) / int32(st::stickerPanSize.width()));
} }
void MentionsInner::mouseMoveEvent(QMouseEvent *e) { void MentionsInner::mouseMoveEvent(QMouseEvent *e) {
@ -4514,7 +4512,7 @@ void MentionsDropdown::setBoundings(QRect boundings) {
void MentionsDropdown::recount(bool resetScroll) { void MentionsDropdown::recount(bool resetScroll) {
int32 h = 0, oldst = _scroll.scrollTop(), st = oldst, maxh = 4.5 * st::mentionHeight; int32 h = 0, oldst = _scroll.scrollTop(), st = oldst, maxh = 4.5 * st::mentionHeight;
if (!_srows.isEmpty()) { if (!_srows.isEmpty()) {
int32 stickersPerRow = int32(_boundings.width() - 2 * st::stickerPanPadding) / int32(st::stickerPanSize.width()); int32 stickersPerRow = qMax(1, int32(_boundings.width() - 2 * st::stickerPanPadding) / int32(st::stickerPanSize.width()));
int32 rows = rowscount(_srows.size(), stickersPerRow); int32 rows = rowscount(_srows.size(), stickersPerRow);
h = st::stickerPanPadding + rows * st::stickerPanSize.height(); h = st::stickerPanPadding + rows * st::stickerPanSize.height();
} else if (!_mrows.isEmpty()) { } else if (!_mrows.isEmpty()) {

View File

@ -178,7 +178,7 @@ namespace Notify {
namespace Global { namespace Global {
struct Data { struct Data {
uint64 LaunchId; uint64 LaunchId = 0;
}; };
Data *_data = 0; Data *_data = 0;

View File

@ -2499,6 +2499,7 @@ MsgId History::msgIdForRead() const {
int32 History::geomResize(int32 newWidth, int32 *ytransform, const HistoryItem *resizedItem) { int32 History::geomResize(int32 newWidth, int32 *ytransform, const HistoryItem *resizedItem) {
if (width != newWidth) resizedItem = 0; // recount all items if (width != newWidth) resizedItem = 0; // recount all items
if (width != newWidth || resizedItem) { if (width != newWidth || resizedItem) {
width = newWidth;
int32 y = 0; int32 y = 0;
for (Blocks::iterator i = blocks.begin(), e = blocks.end(); i != e; ++i) { for (Blocks::iterator i = blocks.begin(), e = blocks.end(); i != e; ++i) {
HistoryBlock *block = *i; HistoryBlock *block = *i;
@ -2513,7 +2514,6 @@ int32 History::geomResize(int32 newWidth, int32 *ytransform, const HistoryItem *
ytransform = 0; ytransform = 0;
} }
} }
width = newWidth;
height = y; height = y;
} }
return height; return height;

View File

@ -30,13 +30,6 @@ namespace {
QMutex debugLogMutex, mainLogMutex; QMutex debugLogMutex, mainLogMutex;
class _StreamCreator {
public:
~_StreamCreator() {
logsClose();
}
};
QString debugLogEntryStart() { QString debugLogEntryStart() {
static uint32 logEntry = 0; static uint32 logEntry = 0;
@ -45,7 +38,7 @@ namespace {
QThread *thread = QThread::currentThread(); QThread *thread = QThread::currentThread();
MTPThread *mtpThread = qobject_cast<MTPThread*>(thread); MTPThread *mtpThread = qobject_cast<MTPThread*>(thread);
uint32 threadId = mtpThread ? mtpThread->getThreadId() : 0; uint32 threadId = mtpThread ? mtpThread->getThreadId() : 0;
return QString("[%1 %2-%3]").arg(tm.toString("hh:mm:ss.zzz")).arg(QString("%1").arg(threadId, 2, 10, zero)).arg(++logEntry, 7, 10, zero); return QString("[%1 %2-%3]").arg(tm.toString("hh:mm:ss.zzz")).arg(QString("%1").arg(threadId, 2, 10, zero)).arg(++logEntry, 7, 10, zero);
} }
} }
@ -179,9 +172,8 @@ void moveOldDataFiles(const QString &wasDir) {
} }
} }
void logsInit() { bool logsInit() {
static _StreamCreator streamCreator; t_assert(mainLogStream == 0);
if (mainLogStream) return;
QFile beta(cExeDir() + qsl("TelegramBeta_data/tdata/beta")); QFile beta(cExeDir() + qsl("TelegramBeta_data/tdata/beta"));
if (cBetaVersion()) { if (cBetaVersion()) {
@ -283,6 +275,7 @@ void logsInit() {
} }
QDir().setCurrent(cWorkingDir()); QDir().setCurrent(cWorkingDir());
return true;
} }
void logsInitDebug() { void logsInitDebug() {
@ -398,7 +391,7 @@ void logsClose() {
} }
QString logVectorLong(const QVector<MTPlong> &ids) { QString logVectorLong(const QVector<MTPlong> &ids) {
if (!ids.size()) return "[void list]"; if (!ids.size()) return "[]";
QString idsStr = QString("[%1").arg(ids.cbegin()->v); QString idsStr = QString("[%1").arg(ids.cbegin()->v);
for (QVector<MTPlong>::const_iterator i = ids.cbegin() + 1, e = ids.cend(); i != e; ++i) { for (QVector<MTPlong>::const_iterator i = ids.cbegin() + 1, e = ids.cend(); i != e; ++i) {
idsStr += QString(", %2").arg(i->v); idsStr += QString(", %2").arg(i->v);
@ -407,7 +400,7 @@ QString logVectorLong(const QVector<MTPlong> &ids) {
} }
QString logVectorLong(const QVector<uint64> &ids) { QString logVectorLong(const QVector<uint64> &ids) {
if (!ids.size()) return "[void list]"; if (!ids.size()) return "[]";
QString idsStr = QString("[%1").arg(*ids.cbegin()); QString idsStr = QString("[%1").arg(*ids.cbegin());
for (QVector<uint64>::const_iterator i = ids.cbegin() + 1, e = ids.cend(); i != e; ++i) { for (QVector<uint64>::const_iterator i = ids.cbegin() + 1, e = ids.cend(); i != e; ++i) {
idsStr += QString(", %2").arg(*i); idsStr += QString(", %2").arg(*i);

View File

@ -92,6 +92,6 @@ inline void t_assert_fail(const char *message, const char *file, int32 line) {
#define t_assert_c(condition, comment) t_assert_full(condition, "\"" #condition "\" (" comment ")", __FILE__, __LINE__) #define t_assert_c(condition, comment) t_assert_full(condition, "\"" #condition "\" (" comment ")", __FILE__, __LINE__)
#define t_assert(condition) t_assert_full(condition, "\"" #condition "\"", __FILE__, __LINE__) #define t_assert(condition) t_assert_full(condition, "\"" #condition "\"", __FILE__, __LINE__)
void logsInit(); bool logsInit();
void logsInitDebug(); void logsInitDebug();
void logsClose(); void logsClose();

View File

@ -25,11 +25,9 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "localstorage.h" #include "localstorage.h"
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
#ifdef _NEED_WIN_GENERATE_DUMP #ifdef Q_OS_WIN
_oldWndExceptionFilter = SetUnhandledExceptionFilter(_exceptionFilter); _oldWndExceptionFilter = SetUnhandledExceptionFilter(_exceptionFilter);
#endif // CAPIHook apiHook("kernel32.dll", "SetUnhandledExceptionFilter", (PROC)RedirectedSetUnhandledExceptionFilter);
#ifdef _NEED_LINUX_GENERATE_DUMP
//signal(SIGSEGV, _sigsegvHandler);
#endif #endif
settingsParseArgs(argc, argv); settingsParseArgs(argc, argv);
@ -40,7 +38,11 @@ int main(int argc, char *argv[]) {
return psCleanup(); return psCleanup();
} }
} }
logsInit(); if (!logsInit()) {
return 0;
}
installSignalHandlers();
Global::Initializer _init; Global::Initializer _init;
@ -58,7 +60,7 @@ int main(int argc, char *argv[]) {
if (cDebug()) { if (cDebug()) {
LOG(("Application Info: Telegram started in debug mode")); LOG(("Application Info: Telegram started in debug mode"));
for (int32 i = 0; i < argc; ++i) { for (int32 i = 0; i < argc; ++i) {
LOG(("Argument: %1").arg(QString::fromLocal8Bit(argv[i]))); LOG(("Argument: %1").arg(fromUtf8Safe(argv[i])));
} }
QStringList logs = psInitLogs(); QStringList logs = psInitLogs();
for (int32 i = 0, l = logs.size(); i < l; ++i) { for (int32 i = 0, l = logs.size(); i < l; ++i) {

View File

@ -1,17 +1,17 @@
/* /*
This file is part of Telegram Desktop, This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
It is distributed in the hope that it will be useful, It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
*/ */
@ -667,7 +667,7 @@ void PsMainWindow::psUpdateCounter() {
} else if (trayIcon) { } else if (trayIcon) {
int32 counter = App::histories().unreadFull - (cIncludeMuted() ? 0 : App::histories().unreadMuted); int32 counter = App::histories().unreadFull - (cIncludeMuted() ? 0 : App::histories().unreadMuted);
bool muted = cIncludeMuted() ? (App::histories().unreadMuted >= counter) : false; bool muted = cIncludeMuted() ? (App::histories().unreadMuted >= counter) : false;
style::color bg = muted ? st::counterMuteBG : st::counterBG; style::color bg = muted ? st::counterMuteBG : st::counterBG;
QIcon iconSmall; QIcon iconSmall;
iconSmall.addPixmap(QPixmap::fromImage(iconWithCounter(16, counter, bg, true), Qt::ColorOnly)); iconSmall.addPixmap(QPixmap::fromImage(iconWithCounter(16, counter, bg, true), Qt::ColorOnly));
@ -1072,7 +1072,7 @@ QString psCurrentLanguage() {
namespace { namespace {
QString _psHomeDir() { QString _psHomeDir() {
struct passwd *pw = getpwuid(getuid()); struct passwd *pw = getpwuid(getuid());
return (pw && pw->pw_dir && strlen(pw->pw_dir)) ? (QString::fromLocal8Bit(pw->pw_dir) + '/') : QString(); return (pw && pw->pw_dir && strlen(pw->pw_dir)) ? (fromUtf8Safe(pw->pw_dir) + '/') : QString();
} }
} }
@ -1086,7 +1086,7 @@ QString psDownloadPath() {
} }
QString psCurrentExeDirectory(int argc, char *argv[]) { QString psCurrentExeDirectory(int argc, char *argv[]) {
QString first = argc ? QString::fromLocal8Bit(argv[0]) : QString(); QString first = argc ? fromUtf8Safe(argv[0]) : QString();
if (!first.isEmpty()) { if (!first.isEmpty()) {
QFileInfo info(first); QFileInfo info(first);
if (info.isSymLink()) { if (info.isSymLink()) {
@ -1100,7 +1100,7 @@ QString psCurrentExeDirectory(int argc, char *argv[]) {
} }
QString psCurrentExeName(int argc, char *argv[]) { QString psCurrentExeName(int argc, char *argv[]) {
QString first = argc ? QString::fromLocal8Bit(argv[0]) : QString(); QString first = argc ? fromUtf8Safe(argv[0]) : QString();
if (!first.isEmpty()) { if (!first.isEmpty()) {
QFileInfo info(first); QFileInfo info(first);
if (info.isSymLink()) { if (info.isSymLink()) {

View File

@ -1,17 +1,17 @@
/* /*
This file is part of Telegram Desktop, This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
It is distributed in the hope that it will be useful, It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
*/ */
@ -83,7 +83,7 @@ void MacPrivate::notifyClicked(unsigned long long peer, int msgid) {
void MacPrivate::notifyReplied(unsigned long long peer, int msgid, const char *str) { void MacPrivate::notifyReplied(unsigned long long peer, int msgid, const char *str) {
History *history = App::history(PeerId(peer)); History *history = App::history(PeerId(peer));
App::main()->sendMessage(history, QString::fromUtf8(str), (msgid > 0 && !history->peer->isUser()) ? msgid : 0, false); App::main()->sendMessage(history, QString::fromUtf8(str), (msgid > 0 && !history->peer->isUser()) ? msgid : 0, false);
} }
@ -592,7 +592,7 @@ QString psDownloadPath() {
} }
QString psCurrentExeDirectory(int argc, char *argv[]) { QString psCurrentExeDirectory(int argc, char *argv[]) {
QString first = argc ? QString::fromLocal8Bit(argv[0]) : QString(); QString first = argc ? fromUtf8Safe(argv[0]) : QString();
if (!first.isEmpty()) { if (!first.isEmpty()) {
QFileInfo info(first); QFileInfo info(first);
if (info.exists()) { if (info.exists()) {
@ -603,7 +603,7 @@ QString psCurrentExeDirectory(int argc, char *argv[]) {
} }
QString psCurrentExeName(int argc, char *argv[]) { QString psCurrentExeName(int argc, char *argv[]) {
QString first = argc ? QString::fromLocal8Bit(argv[0]) : QString(); QString first = argc ? fromUtf8Safe(argv[0]) : QString();
if (!first.isEmpty()) { if (!first.isEmpty()) {
QFileInfo info(first); QFileInfo info(first);
if (info.exists()) { if (info.exists()) {

View File

@ -106,7 +106,7 @@ namespace {
bool sessionLoggedOff = false; bool sessionLoggedOff = false;
UINT tbCreatedMsgId = 0; UINT tbCreatedMsgId = 0;
ComPtr<ITaskbarList3> taskbarList; ComPtr<ITaskbarList3> taskbarList;
ComPtr<IToastNotificationManagerStatics> toastNotificationManager; ComPtr<IToastNotificationManagerStatics> toastNotificationManager;
@ -132,7 +132,7 @@ namespace {
HWND createTaskbarHider() { HWND createTaskbarHider() {
HINSTANCE appinst = (HINSTANCE)GetModuleHandle(0); HINSTANCE appinst = (HINSTANCE)GetModuleHandle(0);
HWND hWnd = 0; HWND hWnd = 0;
QString cn = QString("TelegramTaskbarHider"); QString cn = QString("TelegramTaskbarHider");
LPCWSTR _cn = (LPCWSTR)cn.utf16(); LPCWSTR _cn = (LPCWSTR)cn.utf16();
WNDCLASSEX wc; WNDCLASSEX wc;
@ -153,7 +153,7 @@ namespace {
DEBUG_LOG(("Application Error: could not register taskbar hider window class, error: %1").arg(GetLastError())); DEBUG_LOG(("Application Error: could not register taskbar hider window class, error: %1").arg(GetLastError()));
return hWnd; return hWnd;
} }
hWnd = CreateWindowEx(WS_EX_TOOLWINDOW, _cn, 0, WS_POPUP, 0, 0, 0, 0, 0, 0, appinst, 0); hWnd = CreateWindowEx(WS_EX_TOOLWINDOW, _cn, 0, WS_POPUP, 0, 0, 0, 0, 0, 0, appinst, 0);
if (!hWnd) { if (!hWnd) {
DEBUG_LOG(("Application Error: could not create taskbar hider window class, error: %1").arg(GetLastError())); DEBUG_LOG(("Application Error: could not create taskbar hider window class, error: %1").arg(GetLastError()));
@ -186,12 +186,12 @@ namespace {
hwnds[i] = 0; hwnds[i] = 0;
} }
} }
void setColor(QColor c) { void setColor(QColor c) {
r = c.red(); r = c.red();
g = c.green(); g = c.green();
b = c.blue(); b = c.blue();
if (!hwnds[0]) return; if (!hwnds[0]) return;
Gdiplus::SolidBrush brush(Gdiplus::Color(_alphas[0], r, g, b)); Gdiplus::SolidBrush brush(Gdiplus::Color(_alphas[0], r, g, b));
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
@ -251,7 +251,7 @@ namespace {
Gdiplus::GdiplusStartupInput gdiplusStartupInput; Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken; ULONG_PTR gdiplusToken;
Gdiplus::Status gdiRes = Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); Gdiplus::Status gdiRes = Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
if (gdiRes != Gdiplus::Ok) { if (gdiRes != Gdiplus::Ok) {
LOG(("Application Error: could not init GDI+, error: %1").arg((int)gdiRes)); LOG(("Application Error: could not init GDI+, error: %1").arg((int)gdiRes));
return false; return false;
@ -460,7 +460,7 @@ namespace {
from = _fullsize - (_size - _shift); from = _fullsize - (_size - _shift);
max_w *= 2; max_w *= 2;
for (int i = 0; i < 4; i += 2) { for (int i = 0; i < 4; i += 2) {
DeleteObject(bitmaps[i]); DeleteObject(bitmaps[i]);
bitmaps[i] = CreateCompatibleBitmap(screenDC, max_w, _size); bitmaps[i] = CreateCompatibleBitmap(screenDC, max_w, _size);
SelectObject(dcs[i], bitmaps[i]); SelectObject(dcs[i], bitmaps[i]);
} }
@ -549,7 +549,7 @@ namespace {
_y = y; _y = y;
_w = w; _w = w;
_h = h; _h = h;
if (hidden && (changes & _PsShadowShown)) { if (hidden && (changes & _PsShadowShown)) {
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
SetWindowPos(hwnds[i], hwnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE); SetWindowPos(hwnds[i], hwnd, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE);
@ -680,7 +680,7 @@ namespace {
typedef HRESULT (FAR STDAPICALLTYPE *f_shOpenWithDialog)(HWND hwndParent, const OPENASINFO *poainfo); typedef HRESULT (FAR STDAPICALLTYPE *f_shOpenWithDialog)(HWND hwndParent, const OPENASINFO *poainfo);
f_shOpenWithDialog shOpenWithDialog = 0; f_shOpenWithDialog shOpenWithDialog = 0;
typedef HRESULT (FAR STDAPICALLTYPE *f_shAssocEnumHandlers)(PCWSTR pszExtra, ASSOC_FILTER afFilter, IEnumAssocHandlers **ppEnumHandler); typedef HRESULT (FAR STDAPICALLTYPE *f_shAssocEnumHandlers)(PCWSTR pszExtra, ASSOC_FILTER afFilter, IEnumAssocHandlers **ppEnumHandler);
f_shAssocEnumHandlers shAssocEnumHandlers = 0; f_shAssocEnumHandlers shAssocEnumHandlers = 0;
@ -695,7 +695,7 @@ namespace {
typedef HRESULT (FAR STDAPICALLTYPE *f_shQueryUserNotificationState)(QUERY_USER_NOTIFICATION_STATE *pquns); typedef HRESULT (FAR STDAPICALLTYPE *f_shQueryUserNotificationState)(QUERY_USER_NOTIFICATION_STATE *pquns);
f_shQueryUserNotificationState shQueryUserNotificationState = 0; f_shQueryUserNotificationState shQueryUserNotificationState = 0;
typedef HRESULT (FAR STDAPICALLTYPE *f_setCurrentProcessExplicitAppUserModelID)(__in PCWSTR AppID); typedef HRESULT (FAR STDAPICALLTYPE *f_setCurrentProcessExplicitAppUserModelID)(__in PCWSTR AppID);
f_setCurrentProcessExplicitAppUserModelID setCurrentProcessExplicitAppUserModelID = 0; f_setCurrentProcessExplicitAppUserModelID setCurrentProcessExplicitAppUserModelID = 0;
@ -849,7 +849,7 @@ namespace {
QTimer::singleShot(0, Application::wnd(), SLOT(updateCounter())); QTimer::singleShot(0, Application::wnd(), SLOT(updateCounter()));
Application::wnd()->update(); Application::wnd()->update();
} return false; } return false;
case WM_NCPAINT: if (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS8) return false; *result = 0; return true; case WM_NCPAINT: if (QSysInfo::WindowsVersion >= QSysInfo::WV_WINDOWS8) return false; *result = 0; return true;
case WM_NCCALCSIZE: { case WM_NCCALCSIZE: {
@ -936,7 +936,7 @@ namespace {
case HitTestBottomLeft: *result = HTBOTTOMLEFT; break; case HitTestBottomLeft: *result = HTBOTTOMLEFT; break;
case HitTestLeft: *result = HTLEFT; break; case HitTestLeft: *result = HTLEFT; break;
case HitTestTopLeft: *result = HTTOPLEFT; break; case HitTestTopLeft: *result = HTTOPLEFT; break;
case HitTestNone: case HitTestNone:
default: *result = HTTRANSPARENT; break; default: *result = HTTRANSPARENT; break;
}; };
} return true; } return true;
@ -951,7 +951,7 @@ namespace {
GetWindowRect(hWnd, &r); GetWindowRect(hWnd, &r);
HitTestType res = Application::wnd()->hitTest(QPoint(p.x - r.left + dleft, p.y - r.top + dtop)); HitTestType res = Application::wnd()->hitTest(QPoint(p.x - r.left + dleft, p.y - r.top + dtop));
switch (res) { switch (res) {
case HitTestIcon: case HitTestIcon:
if (menuHidden && getms() < menuHidden + 10) { if (menuHidden && getms() < menuHidden + 10) {
menuHidden = 0; menuHidden = 0;
if (getms() < menuShown + GetDoubleClickTime()) { if (getms() < menuShown + GetDoubleClickTime()) {
@ -1229,7 +1229,7 @@ void PsMainWindow::psInitFrameless() {
if (!ps_hWnd) return; if (!ps_hWnd) return;
if (useWtsapi) wtsRegisterSessionNotification(ps_hWnd, NOTIFY_FOR_THIS_SESSION); if (useWtsapi) wtsRegisterSessionNotification(ps_hWnd, NOTIFY_FOR_THIS_SESSION);
if (frameless) { if (frameless) {
setWindowFlags(Qt::FramelessWindowHint); setWindowFlags(Qt::FramelessWindowHint);
} }
@ -1395,7 +1395,7 @@ void PsMainWindow::psUpdateMargins() {
RECT w, m; RECT w, m;
GetWindowRect(ps_hWnd, &w); GetWindowRect(ps_hWnd, &w);
m = w; m = w;
HMONITOR hMonitor = MonitorFromRect(&w, MONITOR_DEFAULTTONEAREST); HMONITOR hMonitor = MonitorFromRect(&w, MONITOR_DEFAULTTONEAREST);
if (hMonitor) { if (hMonitor) {
MONITORINFO mi; MONITORINFO mi;
@ -1915,7 +1915,7 @@ void psDoFixPrevious() {
LSTATUS newKeyRes2 = RegOpenKeyEx(HKEY_CURRENT_USER, newKeyStr2.toStdWString().c_str(), 0, KEY_READ, &newKey2); LSTATUS newKeyRes2 = RegOpenKeyEx(HKEY_CURRENT_USER, newKeyStr2.toStdWString().c_str(), 0, KEY_READ, &newKey2);
LSTATUS oldKeyRes1 = RegOpenKeyEx(HKEY_LOCAL_MACHINE, oldKeyStr1.toStdWString().c_str(), 0, KEY_READ, &oldKey1); LSTATUS oldKeyRes1 = RegOpenKeyEx(HKEY_LOCAL_MACHINE, oldKeyStr1.toStdWString().c_str(), 0, KEY_READ, &oldKey1);
LSTATUS oldKeyRes2 = RegOpenKeyEx(HKEY_LOCAL_MACHINE, oldKeyStr2.toStdWString().c_str(), 0, KEY_READ, &oldKey2); LSTATUS oldKeyRes2 = RegOpenKeyEx(HKEY_LOCAL_MACHINE, oldKeyStr2.toStdWString().c_str(), 0, KEY_READ, &oldKey2);
bool existNew1 = (newKeyRes1 == ERROR_SUCCESS) && (RegQueryValueEx(newKey1, L"InstallDate", 0, &checkType, (BYTE*)checkStr, &checkSize) == ERROR_SUCCESS); checkSize = bufSize * 2; bool existNew1 = (newKeyRes1 == ERROR_SUCCESS) && (RegQueryValueEx(newKey1, L"InstallDate", 0, &checkType, (BYTE*)checkStr, &checkSize) == ERROR_SUCCESS); checkSize = bufSize * 2;
bool existNew2 = (newKeyRes2 == ERROR_SUCCESS) && (RegQueryValueEx(newKey2, L"InstallDate", 0, &checkType, (BYTE*)checkStr, &checkSize) == ERROR_SUCCESS); checkSize = bufSize * 2; bool existNew2 = (newKeyRes2 == ERROR_SUCCESS) && (RegQueryValueEx(newKey2, L"InstallDate", 0, &checkType, (BYTE*)checkStr, &checkSize) == ERROR_SUCCESS); checkSize = bufSize * 2;
bool existOld1 = (oldKeyRes1 == ERROR_SUCCESS) && (RegQueryValueEx(oldKey1, L"InstallDate", 0, &checkType, (BYTE*)checkStr, &checkSize) == ERROR_SUCCESS); checkSize = bufSize * 2; bool existOld1 = (oldKeyRes1 == ERROR_SUCCESS) && (RegQueryValueEx(oldKey1, L"InstallDate", 0, &checkType, (BYTE*)checkStr, &checkSize) == ERROR_SUCCESS); checkSize = bufSize * 2;
@ -2048,7 +2048,7 @@ bool psShowOpenWithMenu(int x, int y, const QString &file) {
ULONG ulFetched = 0; ULONG ulFetched = 0;
hr = assocHandlers->Next(1, &handler, &ulFetched); hr = assocHandlers->Next(1, &handler, &ulFetched);
if (FAILED(hr) || hr == S_FALSE || !ulFetched) break; if (FAILED(hr) || hr == S_FALSE || !ulFetched) break;
LPWSTR name = 0; LPWSTR name = 0;
if (SUCCEEDED(handler->GetUIName(&name))) { if (SUCCEEDED(handler->GetUIName(&name))) {
LPWSTR icon = 0; LPWSTR icon = 0;
@ -2063,7 +2063,7 @@ bool psShowOpenWithMenu(int x, int y, const QString &file) {
} else { } else {
handler->Release(); handler->Release();
} }
} while (hr != S_FALSE); } while (hr != S_FALSE);
assocHandlers->Release(); assocHandlers->Release();
} }
@ -2201,7 +2201,7 @@ namespace {
} }
return true; return true;
} }
bool _psSetKeyValue(HKEY rkey, LPCWSTR value, QString v) { bool _psSetKeyValue(HKEY rkey, LPCWSTR value, QString v) {
static const int bufSize = 4096; static const int bufSize = 4096;
DWORD defaultType, defaultSize = bufSize * 2; DWORD defaultType, defaultSize = bufSize * 2;
@ -2352,7 +2352,6 @@ void psUpdateOverlayed(TWidget *widget) {
if (!wv) widget->setAttribute(Qt::WA_WState_Visible, false); if (!wv) widget->setAttribute(Qt::WA_WState_Visible, false);
} }
#ifdef _NEED_WIN_GENERATE_DUMP
static const WCHAR *_programName = AppName; // folder in APPDATA, if current path is unavailable for writing static const WCHAR *_programName = AppName; // folder in APPDATA, if current path is unavailable for writing
static const WCHAR *_exeName = L"Telegram.exe"; static const WCHAR *_exeName = L"Telegram.exe";
@ -2396,16 +2395,16 @@ HANDLE _generateDumpFileAtPath(const WCHAR *path) {
GetLocalTime(&stLocalTime); GetLocalTime(&stLocalTime);
if (cBetaVersion()) { if (cBetaVersion()) {
wsprintf(szFileName, L"%s%s-%ld-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp", wsprintf(szFileName, L"%s%s-%ld-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",
szPath, szExeName, cBetaVersion(), szPath, szExeName, cBetaVersion(),
stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond,
GetCurrentProcessId(), GetCurrentThreadId()); GetCurrentProcessId(), GetCurrentThreadId());
} else { } else {
wsprintf(szFileName, L"%s%s-%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp", wsprintf(szFileName, L"%s%s-%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",
szPath, szExeName, AppVersionStr, szPath, szExeName, AppVersionStr,
stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond,
GetCurrentProcessId(), GetCurrentThreadId()); GetCurrentProcessId(), GetCurrentThreadId());
} }
return CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0); return CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
@ -2455,9 +2454,16 @@ void _generateDump(EXCEPTION_POINTERS* pExceptionPointers) {
LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers) { LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers) {
_generateDump(pExceptionPointers); _generateDump(pExceptionPointers);
return _oldWndExceptionFilter ? (*_oldWndExceptionFilter)(pExceptionPointers) : EXCEPTION_CONTINUE_SEARCH; return _oldWndExceptionFilter ? (*_oldWndExceptionFilter)(pExceptionPointers) : EXCEPTION_CONTINUE_SEARCH;
}
// see http://www.codeproject.com/Articles/154686/SetUnhandledExceptionFilter-and-the-C-C-Runtime-Li
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI RedirectedSetUnhandledExceptionFilter(_In_opt_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) {
// When the CRT calls SetUnhandledExceptionFilter with NULL parameter
// our handler will not get removed.
_oldWndExceptionFilter = lpTopLevelExceptionFilter;
return 0;
} }
#endif
class StringReferenceWrapper { class StringReferenceWrapper {
public: public:
@ -2595,7 +2601,7 @@ public:
~ToastEventHandler() { ~ToastEventHandler() {
} }
// DesktopToastActivatedEventHandler // DesktopToastActivatedEventHandler
IFACEMETHODIMP Invoke(_In_ IToastNotification *sender, _In_ IInspectable* args) { IFACEMETHODIMP Invoke(_In_ IToastNotification *sender, _In_ IInspectable* args) {
ToastNotifications::iterator i = toastNotifications.find(_peerId); ToastNotifications::iterator i = toastNotifications.find(_peerId);
if (i != toastNotifications.cend()) { if (i != toastNotifications.cend()) {
@ -2867,7 +2873,7 @@ void CheckPinnedAppUserModelId() {
QString path = pinnedPath(); QString path = pinnedPath();
std::wstring p = QDir::toNativeSeparators(path).toStdWString(); std::wstring p = QDir::toNativeSeparators(path).toStdWString();
WCHAR src[MAX_PATH]; WCHAR src[MAX_PATH];
GetModuleFileName(GetModuleHandle(0), src, MAX_PATH); GetModuleFileName(GetModuleHandle(0), src, MAX_PATH);
BY_HANDLE_FILE_INFORMATION srcinfo = { 0 }; BY_HANDLE_FILE_INFORMATION srcinfo = { 0 };
@ -2913,7 +2919,7 @@ void CheckPinnedAppUserModelId() {
BOOL dstres = GetFileInformationByHandle(dstfile, &dstinfo); BOOL dstres = GetFileInformationByHandle(dstfile, &dstinfo);
CloseHandle(dstfile); CloseHandle(dstfile);
if (!dstres) continue; if (!dstres) continue;
if (srcinfo.dwVolumeSerialNumber == dstinfo.dwVolumeSerialNumber && srcinfo.nFileIndexLow == dstinfo.nFileIndexLow && srcinfo.nFileIndexHigh == dstinfo.nFileIndexHigh) { if (srcinfo.dwVolumeSerialNumber == dstinfo.dwVolumeSerialNumber && srcinfo.nFileIndexLow == dstinfo.nFileIndexLow && srcinfo.nFileIndexHigh == dstinfo.nFileIndexHigh) {
ComPtr<IPropertyStore> propertyStore; ComPtr<IPropertyStore> propertyStore;
hr = shellLink.As(&propertyStore); hr = shellLink.As(&propertyStore);
@ -3005,7 +3011,7 @@ void CleanupAppUserModelIdShortcut() {
bool ValidateAppUserModelIdShortcutAt(const QString &path) { bool ValidateAppUserModelIdShortcutAt(const QString &path) {
static const int maxFileLen = MAX_PATH * 10; static const int maxFileLen = MAX_PATH * 10;
std::wstring p = QDir::toNativeSeparators(path).toStdWString(); std::wstring p = QDir::toNativeSeparators(path).toStdWString();
DWORD attributes = GetFileAttributes(p.c_str()); DWORD attributes = GetFileAttributes(p.c_str());

View File

@ -113,10 +113,9 @@ private:
void psDestroyIcons(); void psDestroyIcons();
}; };
#ifdef _NEED_WIN_GENERATE_DUMP
extern LPTOP_LEVEL_EXCEPTION_FILTER _oldWndExceptionFilter; extern LPTOP_LEVEL_EXCEPTION_FILTER _oldWndExceptionFilter;
LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers); LONG CALLBACK _exceptionFilter(EXCEPTION_POINTERS* pExceptionPointers);
#endif LPTOP_LEVEL_EXCEPTION_FILTER WINAPI RedirectedSetUnhandledExceptionFilter(_In_opt_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);
class PsApplication : public QApplication { class PsApplication : public QApplication {
Q_OBJECT Q_OBJECT

View File

@ -199,7 +199,7 @@ void settingsParseArgs(int argc, char *argv[]) {
} else if (string("-many") == argv[i]) { } else if (string("-many") == argv[i]) {
gManyInstance = true; gManyInstance = true;
} else if (string("-key") == argv[i] && i + 1 < argc) { } else if (string("-key") == argv[i] && i + 1 < argc) {
gKeyFile = QString::fromLocal8Bit(argv[++i]); gKeyFile = fromUtf8Safe(argv[++i]);
} else if (string("-autostart") == argv[i]) { } else if (string("-autostart") == argv[i]) {
gFromAutoStart = true; gFromAutoStart = true;
} else if (string("-noupdate") == argv[i]) { } else if (string("-noupdate") == argv[i]) {
@ -210,15 +210,15 @@ void settingsParseArgs(int argc, char *argv[]) {
gStartInTray = true; gStartInTray = true;
} else if (string("-sendpath") == argv[i] && i + 1 < argc) { } else if (string("-sendpath") == argv[i] && i + 1 < argc) {
for (++i; i < argc; ++i) { for (++i; i < argc; ++i) {
gSendPaths.push_back(QString::fromLocal8Bit(argv[i])); gSendPaths.push_back(fromUtf8Safe(argv[i]));
} }
} else if (string("-workdir") == argv[i] && i + 1 < argc) { } else if (string("-workdir") == argv[i] && i + 1 < argc) {
QString dir = QString::fromLocal8Bit(argv[++i]); QString dir = fromUtf8Safe(argv[++i]);
if (QDir().exists(dir)) { if (QDir().exists(dir)) {
gWorkingDir = dir; gWorkingDir = dir;
} }
} else if (string("--") == argv[i] && i + 1 < argc) { } else if (string("--") == argv[i] && i + 1 < argc) {
gStartUrl = QString::fromLocal8Bit(argv[++i]); gStartUrl = fromUtf8Safe(argv[++i]);
} }
} }
} }

View File

@ -45,12 +45,6 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include <lzma.h> #include <lzma.h>
#endif #endif
#if defined Q_OS_WIN
#define _NEED_WIN_GENERATE_DUMP
#elif defined Q_OS_LINUX32 || defined Q_OS_LINUX64
#define _NEED_LINUX_GENERATE_DUMP
#endif
extern "C" { extern "C" {
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>

View File

@ -22,6 +22,8 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
#include "application.h" #include "application.h"
#include <signal.h>
uint64 _SharedMemoryLocation[4] = { 0x00, 0x01, 0x02, 0x03 }; uint64 _SharedMemoryLocation[4] = { 0x00, 0x01, 0x02, 0x03 };
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
@ -303,6 +305,47 @@ void deinitThirdParty() {
_sslLocks = 0; _sslLocks = 0;
} }
namespace {
FILE *_crashDump = 0;
int _crashDumpNo = 0;
}
void _signalHandler(int signum) {
const char* name = 0;
switch (signum) {
case SIGABRT: name = "SIGABRT"; break;
case SIGSEGV: name = "SIGSEGV"; break;
case SIGILL: name = "SIGILL"; break;
case SIGFPE: name = "SIGFPE"; break;
#ifndef Q_OS_WIN
case SIGBUS: name = "SIGBUS"; break;
case SIGSYS: name = "SIGSYS"; break;
#endif
}
LOG(("Caught signal %1").arg(name));
if (name)
fprintf(stdout, "Caught signal %d (%s)\n", signum, name);
else
fprintf(stdout, "Caught signal %d\n", signum);
//printStackTrace();
}
void installSignalHandlers() {
_crashDump = fopen((cWorkingDir() + qsl("tdata/working")).toUtf8().constData(), "wb");
if (_crashDump) _crashDumpNo = fileno(_crashDump);
signal(SIGABRT, _signalHandler);
signal(SIGSEGV, _signalHandler);
signal(SIGILL, _signalHandler);
signal(SIGFPE, _signalHandler);
#ifndef Q_OS_WIN
signal(SIGBUS, _signalHandler);
signal(SIGSYS, _signalHandler);
#endif
}
bool checkms() { bool checkms() {
int64 unixms = (myunixtime() - _timeStart) * 1000LL + _msAddToUnixtime; int64 unixms = (myunixtime() - _timeStart) * 1000LL + _msAddToUnixtime;
int64 ms = int64(getms(true)); int64 ms = int64(getms(true));

View File

@ -133,6 +133,8 @@ inline void mylocaltime(struct tm * _Tm, const time_t * _Time) {
#endif #endif
} }
void installSignalHandlers();
void initThirdParty(); // called by Global::Initializer void initThirdParty(); // called by Global::Initializer
void deinitThirdParty(); void deinitThirdParty();
@ -233,6 +235,19 @@ private:
#define qsl(s) QStringLiteral(s) #define qsl(s) QStringLiteral(s)
#define qstr(s) QLatin1String(s, sizeof(s) - 1) #define qstr(s) QLatin1String(s, sizeof(s) - 1)
inline QString fromUtf8Safe(const char *str, int32 size = -1) {
if (!str || !size) return QString();
if (size < 0) size = int32(strlen(str));
QString result(QString::fromUtf8(str, size));
QByteArray back = result.toUtf8();
if (back.size() != size || memcmp(back.constData(), str, size)) return QString::fromLocal8Bit(str, size);
return result;
}
inline QString fromUtf8Safe(const QByteArray &str) {
return fromUtf8Safe(str.constData(), str.size());
}
static const QRegularExpression::PatternOptions reMultiline(QRegularExpression::DotMatchesEverythingOption | QRegularExpression::MultilineOption); static const QRegularExpression::PatternOptions reMultiline(QRegularExpression::DotMatchesEverythingOption | QRegularExpression::MultilineOption);
template <typename T> template <typename T>