All windows are now created in the main thread where the main dialog is created. This should fix any weird user32.dll crashes caused by different types of messages sent to the main dialog during destruction of the NSISdl dialog. This also reduces the size of the DLL by 0.5KB :)

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@3444 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
kichik 2004-02-01 18:52:06 +00:00
parent 38d9a9aa37
commit 1ff9789272
4 changed files with 152 additions and 214 deletions

View file

@ -1,4 +1,4 @@
NSISdl 1.1 - HTTP downloading plugin for NSIS NSISdl 1.3 - HTTP downloading plugin for NSIS
--------------------------------------------- ---------------------------------------------
Copyright (C) 2001-2002 Yaroslav Faybishenko & Justin Frankel Copyright (C) 2001-2002 Yaroslav Faybishenko & Justin Frankel

View file

@ -1,5 +1,5 @@
/* /*
NSIS-DL 1.2 - http downloading DLL for NSIS NSIS-DL 1.3 - http downloading DLL for NSIS
Copyright (C) 2001-2002 Yaroslav Faybishenko & Justin Frankel Copyright (C) 2001-2002 Yaroslav Faybishenko & Justin Frankel
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
@ -17,22 +17,13 @@
2. Altered source versions must be plainly marked as such, and must not be 2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software. misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution. 3. This notice may not be removed or altered from any source distribution.
*/
Note: this source code is pretty hacked together right now, improvements
and cleanups will come later.
IMPORTANT: The dialog must have the style "No Parent Notify"
*/
#include <windows.h> #include <windows.h>
#include <stdio.h> #include <stdio.h>
#include <commctrl.h> #include <commctrl.h>
#include "netinc.h" #include "netinc.h"
#include "util.h" #include "util.h"
#include "resource.h"
#include "httpget.h" #include "httpget.h"
#include "../exdll/exdll.h" #include "../exdll/exdll.h"
@ -43,106 +34,165 @@ void *operator new( unsigned int num_bytes )
void operator delete( void *p ) { if (p) GlobalFree(p); } void operator delete( void *p ) { if (p) GlobalFree(p); }
HANDLE hModule; HMODULE hModule;
HWND g_hwndProgressBar; HWND g_hwndProgressBar;
HWND g_hwndStatic;
static int g_cancelled; static int g_cancelled;
long lBusy;
ULONG idThreadOwner;
ULONG ulRefCount;
static void *lpWndProcOld; static void *lpWndProcOld;
BOOL CALLBACK DownloadDialogProc(HWND hwndDlg, static UINT uMsgCreate;
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
return 0;
}
BOOL TryEnterCS() HWND childwnd;
{ HWND hwndL;
DWORD CurThreadID = ::GetCurrentThreadId(); HWND hwndB;
BOOL bRet = TRUE;
long *plBusy = &lBusy;
while (::InterlockedExchange(plBusy, 1) != 0)
{
Sleep(0);
}
if (idThreadOwner == 0)
{
idThreadOwner = CurThreadID;
ulRefCount = 1;
}
else if (idThreadOwner == CurThreadID)
{
ulRefCount++;
}
else
{
bRet = FALSE;
}
::InterlockedExchange(plBusy, 0);
return bRet;
}
void LeaveCS()
{
long *plBusy = &lBusy;
while (::InterlockedExchange(plBusy, 1) != 0)
{
Sleep(0);
}
if (idThreadOwner == ::GetCurrentThreadId())
{
if (--ulRefCount == 0)
{
// No owner from now
idThreadOwner = 0;
}
}
::InterlockedExchange(plBusy, 0);
}
static LRESULT CALLBACK ParentWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) static LRESULT CALLBACK ParentWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{ {
LRESULT Res = 0; if (uMsgCreate && message == uMsgCreate)
while ( !TryEnterCS() ) Sleep(0); {
if (message == WM_COMMAND && LOWORD(wParam) == IDCANCEL) if (wParam)
{
childwnd = FindWindowEx((HWND) lParam, NULL, "#32770", NULL);
hwndL = GetDlgItem(childwnd, 1016);
hwndB = GetDlgItem(childwnd, 1027);
HWND hwndP = GetDlgItem(childwnd, 1004);
HWND hwndS = GetDlgItem(childwnd, 1006);
if (childwnd && hwndP && hwndS)
{
if (IsWindowVisible(hwndL))
ShowWindow(hwndL, SW_HIDE);
else
hwndL = NULL;
if (IsWindowVisible(hwndB))
ShowWindow(hwndB, SW_HIDE);
else
hwndB = NULL;
RECT wndRect, ctlRect;
GetClientRect(childwnd, &wndRect);
GetWindowRect(hwndS, &ctlRect);
HWND s = g_hwndStatic = CreateWindow(
"STATIC",
"",
WS_CHILD | WS_CLIPSIBLINGS | SS_CENTER,
0,
wndRect.bottom / 2 - (ctlRect.bottom - ctlRect.top) / 2,
wndRect.right,
ctlRect.bottom - ctlRect.top,
childwnd,
NULL,
hModule,
NULL
);
DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS;
dwStyle |= GetWindowLong(hwndP, GWL_STYLE) & PBS_SMOOTH;
GetWindowRect(hwndP, &ctlRect);
HWND pb = g_hwndProgressBar = CreateWindow(
"msctls_progress32",
"",
dwStyle,
0,
wndRect.bottom / 2 + (ctlRect.bottom - ctlRect.top) / 2,
wndRect.right,
ctlRect.bottom - ctlRect.top,
childwnd,
NULL,
hModule,
NULL
);
long c;
c = SendMessage(hwndP, PBM_SETBARCOLOR, 0, 0);
SendMessage(hwndP, PBM_SETBARCOLOR, 0, c);
SendMessage(pb, PBM_SETBARCOLOR, 0, c);
c = SendMessage(hwndP, PBM_SETBKCOLOR, 0, 0);
SendMessage(hwndP, PBM_SETBKCOLOR, 0, c);
SendMessage(pb, PBM_SETBKCOLOR, 0, c);
// set font
long hFont = SendMessage((HWND) lParam, WM_GETFONT, 0, 0);
SendMessage(pb, WM_SETFONT, hFont, 0);
SendMessage(s, WM_SETFONT, hFont, 0);
ShowWindow(pb, SW_SHOWNA);
ShowWindow(s, SW_SHOWNA);
}
else
childwnd = NULL;
}
else if (childwnd)
{
if (g_hwndStatic)
{
DestroyWindow(g_hwndStatic);
g_hwndStatic = NULL;
}
if (g_hwndProgressBar)
{
DestroyWindow(g_hwndProgressBar);
g_hwndProgressBar = NULL;
}
if (hwndB)
{
ShowWindow(hwndB, SW_SHOWNA);
hwndB = NULL;
}
if (hwndL)
{
ShowWindow(hwndL, SW_SHOWNA);
hwndL = NULL;
}
childwnd = NULL;
}
}
else if (message == WM_COMMAND && LOWORD(wParam) == IDCANCEL)
{
g_cancelled = 1; g_cancelled = 1;
}
else else
Res = CallWindowProc((long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long))lpWndProcOld,hwnd,message,wParam,lParam); {
LeaveCS(); return CallWindowProc(
return Res; (WNDPROC) lpWndProcOld,
hwnd,
message,
wParam,
lParam
);
}
return 0;
} }
BOOL APIENTRY DllMain( HANDLE _hModule, BOOL APIENTRY DllMain(HINSTANCE _hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{ {
hModule = _hModule; hModule = _hModule;
return TRUE; return TRUE;
} }
static int g_file_size; static int g_file_size;
static DWORD g_dwLastTick = 0; static DWORD g_dwLastTick = 0;
void progress_callback(HWND dlg, char *msg, int read_bytes) void progress_callback(char *msg, int read_bytes)
{ {
// flicker reduction by A. Schiffler // flicker reduction by A. Schiffler
DWORD dwLastTick = g_dwLastTick; DWORD dwLastTick = g_dwLastTick;
DWORD dwThisTick = GetTickCount(); DWORD dwThisTick = GetTickCount();
if (dlg) if (childwnd)
{ {
if (dwThisTick - dwLastTick > 500) if (dwThisTick - dwLastTick > 500)
{ {
SetDlgItemText (dlg, IDC_STATIC2, msg); SetWindowText(g_hwndStatic, msg);
dwLastTick = dwThisTick; dwLastTick = dwThisTick;
} }
if (g_file_size) SendMessage(g_hwndProgressBar, PBM_SETPOS, (WPARAM)MulDiv(read_bytes,30000,g_file_size), 0); if (g_file_size)
SendMessage(g_hwndProgressBar, PBM_SETPOS, (WPARAM) MulDiv(read_bytes, 30000, g_file_size), 0);
g_dwLastTick = dwLastTick; g_dwLastTick = dwLastTick;
} }
} }
@ -161,13 +211,7 @@ __declspec(dllexport) void download (HWND parent,
char buf[1024]; char buf[1024];
char url[1024]; char url[1024];
char filename[1024]; char filename[1024];
HWND hwndAux;
HWND hwndL=0;
HWND hwndB=0;
HWND dlg=0;
HWND childwnd=0;
BOOL bSuccess=FALSE; BOOL bSuccess=FALSE;
RECT r, cr, orig_childRc;
int timeout_ms=30000; int timeout_ms=30000;
char *error=NULL; char *error=NULL;
@ -226,88 +270,19 @@ __declspec(dllexport) void download (HWND parent,
if (parent) if (parent)
{ {
childwnd=FindWindowEx(parent,NULL,"#32770",NULL); uMsgCreate = RegisterWindowMessage("nsisdl create");
hwndL=GetDlgItem(childwnd,1016);
hwndB=GetDlgItem(childwnd,1027);
if ( IsWindowVisible(hwndL) ) ShowWindow(hwndL,SW_HIDE);
else hwndL=NULL;
if (IsWindowVisible(hwndB)) ShowWindow(hwndB,SW_HIDE);
else hwndB=NULL;
lpWndProcOld = (void *)SetWindowLong(parent,GWL_WNDPROC,(long)ParentWndProc); lpWndProcOld = (void *)SetWindowLong(parent,GWL_WNDPROC,(long)ParentWndProc);
dlg = CreateDialog((HINSTANCE)hModule, SendMessage(parent, uMsgCreate, TRUE, (LPARAM) parent);
MAKEINTRESOURCE(IDD_DIALOG1),
parent,
DownloadDialogProc);
if (dlg)
{
int pbid = IDC_PROGRESS1;
HWND hwPb = GetDlgItem(childwnd, 1004);
// Set progress bar style // set initial text
if (GetWindowLong(hwPb, GWL_STYLE) & PBS_SMOOTH) char *p = filename;
pbid = IDC_PROGRESS2; while (*p) p++;
while (*p != '\\' && p != filename) p = CharPrev(filename, p);
HWND pb = g_hwndProgressBar = GetDlgItem(dlg, pbid); wsprintf(buf, szDownloading, p != filename ? p + 1 : p);
SetDlgItemText(childwnd, 1006, buf);
if (hwPb) SetWindowText(g_hwndStatic, szConnecting);
{
long c;
c = SendMessage(hwPb, PBM_SETBARCOLOR, 0, 0);
SendMessage(hwPb, PBM_SETBARCOLOR, 0, c);
SendMessage(pb, PBM_SETBARCOLOR, 0, c);
c = SendMessage(hwPb, PBM_SETBKCOLOR, 0, 0);
SendMessage(hwPb, PBM_SETBKCOLOR, 0, c);
SendMessage(pb, PBM_SETBKCOLOR, 0, c);
}
ShowWindow(pb, SW_SHOWNA);
GetWindowRect(childwnd,&orig_childRc);
GetWindowRect(dlg,&cr);
ScreenToClient(dlg,(LPPOINT)&cr);
ScreenToClient(dlg,((LPPOINT)&cr)+1);
hwndAux = GetDlgItem(childwnd,1016);
GetWindowRect(hwndAux,&r);
ScreenToClient(childwnd,(LPPOINT)&r);
ScreenToClient(childwnd,((LPPOINT)&r)+1);
SetWindowPos(childwnd,0,0,0,r.right-r.left,r.top,SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE);
GetWindowRect(hwndAux,&r);
ScreenToClient(parent,(LPPOINT)&r);
ScreenToClient(parent,((LPPOINT)&r)+1);
SetWindowPos(dlg,0,r.left,r.top,r.right-r.left,cr.bottom-cr.top,SWP_NOACTIVATE|SWP_NOZORDER);
hwndAux = GetDlgItem(dlg,IDC_STATIC2);
GetWindowRect(hwndAux,&cr);
ScreenToClient(dlg,(LPPOINT)&cr);
ScreenToClient(dlg,((LPPOINT)&cr)+1);
SetWindowPos(hwndAux,0,0,0,r.right-r.left,cr.bottom-cr.top,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
hwndAux = GetDlgItem(dlg,pbid);
GetWindowRect(hwndAux,&cr);
ScreenToClient(dlg,(LPPOINT)&cr);
ScreenToClient(dlg,((LPPOINT)&cr)+1);
SetWindowPos(hwndAux,0,0,0,r.right-r.left,cr.bottom-cr.top,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);
char *p=filename;
while (*p) p++;
while (*p != '\\' && p != filename) p=CharPrev(filename,p);
wsprintf(buf,szDownloading, p!=filename?p+1:p);
SetDlgItemText(childwnd,1006,buf);
SetDlgItemText(dlg, IDC_STATIC2, szConnecting);
// set font
long hFont = SendMessage(parent, WM_GETFONT, 0, 0);
SendDlgItemMessage(dlg, pbid, WM_SETFONT, hFont, 0);
SendDlgItemMessage(dlg, IDC_STATIC2, WM_SETFONT, hFont, 0);
ShowWindow(dlg, SW_SHOWNA);
}
// enable the cancel button // enable the cancel button
hwndPrevFocus = GetFocus(); hwndPrevFocus = GetFocus();
@ -365,44 +340,15 @@ __declspec(dllexport) void download (HWND parent,
get->connect (url); get->connect (url);
while (1) { while (1) {
do if (g_cancelled)
{
if ( dlg )
{
MSG msg;
while (PeekMessage(&msg,dlg,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
while (!TryEnterCS()); // Process messages
if (g_cancelled || error)
{
if (dlg)
DestroyWindow(dlg);
dlg = NULL;
if (!error)
error = "cancel"; error = "cancel";
}
LeaveCS();
if (error) if (error)
{ {
if (parent) if (parent)
{ {
SetWindowLong(parent,GWL_WNDPROC,(long)lpWndProcOld); SendMessage(parent, uMsgCreate, FALSE, (LPARAM) parent);
SetWindowLong(parent, GWL_WNDPROC, (long)lpWndProcOld);
if (hwndB) ShowWindow(hwndB,SW_SHOWNA);
if (hwndL) ShowWindow(hwndL,SW_SHOWNA);
SetWindowPos(
childwnd,0,0,0,
orig_childRc.right-orig_childRc.left,
orig_childRc.bottom-orig_childRc.top,
SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOMOVE
);
// Prevent wierd stuff happening if the cancel button happens to be // Prevent wierd stuff happening if the cancel button happens to be
// pressed at the moment we are finishing // pressed at the moment we are finishing
@ -439,7 +385,7 @@ __declspec(dllexport) void download (HWND parent,
} else if (get->get_status () == 1) { } else if (get->get_status () == 1) {
progress_callback(dlg, "Reading headers", 0); progress_callback("Reading headers", 0);
if (last_recv_time+timeout_ms < GetTickCount()) if (last_recv_time+timeout_ms < GetTickCount())
error = "Timed out on getting headers."; error = "Timed out on getting headers.";
@ -452,9 +398,9 @@ __declspec(dllexport) void download (HWND parent,
cl = get->content_length (); cl = get->content_length ();
if (cl == 0) if (cl == 0)
error = "Server did not specify content length."; error = "Server did not specify content length.";
else if (dlg) { else if (g_hwndProgressBar) {
SendMessage(g_hwndProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0,30000)); SendMessage(g_hwndProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, 30000));
g_file_size=cl; g_file_size = cl;
} }
} }
@ -493,7 +439,7 @@ __declspec(dllexport) void download (HWND parent,
rtext, rtext,
remain==1?"":szPlural remain==1?"":szPlural
); );
progress_callback(dlg, buf, sofar); progress_callback(buf, sofar);
} else { } else {
if (sofar < cl) if (sofar < cl)
error = "Server aborted."; error = "Server aborted.";

View file

@ -137,20 +137,12 @@ SOURCE=.\netinc.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\resource.h
# End Source File
# Begin Source File
SOURCE=.\util.h SOURCE=.\util.h
# End Source File # End Source File
# End Group # End Group
# Begin Group "Resource Files" # Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# Begin Source File
SOURCE=.\Script1.rc
# End Source File
# End Group # End Group
# End Target # End Target
# End Project # End Project

Binary file not shown.