NT4/private/windows/rover/filesync/syncui/thread.c
2020-09-30 17:12:29 +02:00

348 lines
8.4 KiB
C

//---------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation 1993-1994
//
// File: thread.c
//
// This files contains the thread creation routines. (These routines
// were swiped from the shell.)
//
// Public API is RunDLLThread().
//
//---------------------------------------------------------------------------
#include "brfprv.h"
#pragma data_seg(DATASEG_READONLY)
static const TCHAR c_szStubWindowClass[] = TEXT("BrfStubWindow32");
#pragma data_seg()
// SHOpenPropSheet uses these messages. It is unclear if
// we need to support this or not.
#define STUBM_SETDATA (WM_USER)
#define STUBM_GETDATA (WM_USER+1)
typedef void (WINAPI * NEWTHREADPROC)(HWND hwndStub,
HINSTANCE hAppInstance,
LPTSTR lpszCmdLine, int nCmdShow);
typedef struct // dlle
{
HINSTANCE hinst;
NEWTHREADPROC lpfn;
} DLLENTRY;
typedef struct _NEWTHREAD_NOTIFY
{
NMHDR hdr;
HICON hIcon;
LPCTSTR lpszTitle;
} NEWTHREAD_NOTIFY;
/*----------------------------------------------------------
Purpose: Parses a command line entry into a DLLENTRY struct.
Returns: TRUE on success
Cond: --
*/
BOOL PRIVATE InitializeDLLEntry(
LPTSTR lpszCmdLine,
DLLENTRY * pdlle)
{
LPTSTR lpStart, lpEnd, lpFunction;
TRACE_MSG(TF_GENERAL, TEXT("RunDLLThread(%s)"), lpszCmdLine);
for (lpStart=lpszCmdLine; ; )
{
// Skip leading blanks
//
while (*lpStart == TEXT(' '))
{
++lpStart;
}
// Check if there are any switches
//
if (*lpStart != TEXT('/'))
{
break;
}
// Look at all the switches; ignore unknown ones
//
for (++lpStart; ; ++lpStart)
{
switch (*lpStart)
{
case TEXT(' '):
case TEXT('\0'):
goto EndSwitches;
break;
// Put any switches we care about here
//
default:
break;
}
}
EndSwitches:
;
}
// We have found the DLL,FN parameter
//
lpEnd = StrChr(lpStart, TEXT(' '));
if (lpEnd)
{
*lpEnd++ = TEXT('\0');
}
// There must be a DLL name and a function name
//
lpFunction = StrChr(lpStart, TEXT(','));
if (!lpFunction)
{
return(FALSE);
}
*lpFunction++ = TEXT('\0');
// Load the library and get the procedure address
// Note that we try to get a module handle first, so we don't need
// to pass full file names around
//
pdlle->hinst = GetModuleHandle(lpStart);
if (pdlle->hinst)
{
TCHAR szName[MAXPATHLEN];
GetModuleFileName(pdlle->hinst, szName, ARRAYSIZE(szName));
LoadLibrary(szName);
}
else
{
pdlle->hinst = LoadLibrary(lpStart);
if (!ISVALIDHINSTANCE(pdlle->hinst))
{
return(FALSE);
}
}
#ifdef UNICODE
{
CHAR szFunction[MAX_PATH] = "";
WideCharToMultiByte(CP_ACP, 0, lpFunction, -1, szFunction, MAX_PATH, NULL, NULL);
pdlle->lpfn = (NEWTHREADPROC)GetProcAddress(pdlle->hinst, szFunction);
}
#else
{
pdlle->lpfn = (NEWTHREADPROC)GetProcAddress(pdlle->hinst, lpFunction);
}
#endif
if (!pdlle->lpfn)
{
FreeLibrary(pdlle->hinst);
return(FALSE);
}
// Copy the rest of the command parameters down
//
if (lpEnd)
{
lstrcpy(lpszCmdLine, lpEnd);
}
else
{
*lpszCmdLine = TEXT('\0');
}
return(TRUE);
}
/*----------------------------------------------------------
Purpose: Handles WM_NOTIFY messages for stub window
Returns: varies
Cond: --
*/
LRESULT PRIVATE StubNotify(
HWND hWnd,
WPARAM wParam,
NEWTHREAD_NOTIFY *lpn)
{
switch (lpn->hdr.code)
{
#ifdef COOLICON
case RDN_TASKINFO:
SetWindowText(hWnd, lpn->lpszTitle ? lpn->lpszTitle : TEXT(""));
g_hIcon = lpn->hIcon ? lpn->hIcon :
LoadIcon(hInst, MAKEINTRESOURCE(IDI_DEFAULT));
break;
#endif
default:
return(DefWindowProc(hWnd, WM_NOTIFY, wParam, (LPARAM)lpn));
}
}
/*----------------------------------------------------------
Purpose: Window proc for thread
Returns: varies
Cond: --
*/
LRESULT CALLBACK WndProc(
HWND hWnd,
UINT iMessage,
WPARAM wParam,
LPARAM lParam)
{
switch(iMessage)
{
case WM_CREATE:
#ifdef COOLICON
g_hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_DEFAULT));
#endif
break;
case WM_DESTROY:
break;
case WM_NOTIFY:
return(StubNotify(hWnd, wParam, (NEWTHREAD_NOTIFY *)lParam));
#ifdef COOLICON
case WM_QUERYDRAGICON:
return(MAKELRESULT(g_hIcon, 0));
#endif
case STUBM_SETDATA:
SetWindowLong(hWnd, 0, wParam);
SetWindowLong(hWnd, 4, lParam);
break;
case STUBM_GETDATA:
*((LONG *)lParam) = GetWindowLong(hWnd, 4);
return GetWindowLong(hWnd, 0);
default:
return DefWindowProc(hWnd, iMessage, wParam, lParam) ;
break;
}
return 0L;
}
/*----------------------------------------------------------
Purpose: Creates a stub window to handle the thread
Returns: handle to window
Cond: --
*/
HWND PRIVATE CreateStubWindow(void)
{
WNDCLASS wndclass;
if (!GetClassInfo(g_hinst, c_szStubWindowClass, &wndclass))
{
wndclass.style = 0 ;
wndclass.lpfnWndProc = (WNDPROC)WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = sizeof(DWORD) * 2 ;
wndclass.hInstance = g_hinst;
wndclass.hIcon = NULL ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = c_szStubWindowClass ;
if (!RegisterClass(&wndclass))
{
return NULL;
}
}
return CreateWindowEx(WS_EX_TOOLWINDOW, c_szStubWindowClass, c_szNULL,
0, 0, 0, 0, 0, NULL, NULL, g_hinst, NULL);
}
/*----------------------------------------------------------
Purpose: Initializes a new thread in our DLL
Returns: 0
Cond: --
*/
DWORD PRIVATE ThreadInitDLL(
LPVOID pszCmdLine)
{
DLLENTRY dlle;
if (InitializeDLLEntry((LPTSTR)pszCmdLine, &dlle))
{
HWND hwndStub = CreateStubWindow();
if (hwndStub)
{
SetForegroundWindow(hwndStub);
dlle.lpfn(hwndStub, g_hinst, pszCmdLine, SW_NORMAL);
DestroyWindow(hwndStub);
}
FreeLibrary(dlle.hinst);
}
GFree(pszCmdLine);
return 0;
}
/*----------------------------------------------------------
Purpose: Start a new thread
This code was swiped from the shell.
Returns: TRUE if the thread was created successfully
Cond: --
*/
BOOL PUBLIC RunDLLThread(
HWND hwnd,
LPCTSTR pszCmdLine,
int nCmdShow)
{
BOOL fSuccess=FALSE; // assume error
LPTSTR pszCopy = GAlloc(CbFromCch(lstrlen(pszCmdLine)+1));
if (pszCopy)
{
DWORD idThread;
HANDLE hthread;
lstrcpy(pszCopy, pszCmdLine);
if (hthread=CreateThread(NULL, 0, ThreadInitDLL, pszCopy, 0, &idThread))
{
// We don't need to communicate with this thread any more.
// Close the handle and let it run and terminate itself.
//
// Notes: In this case, pszCopy will be freed by the thread.
//
CloseHandle(hthread);
fSuccess=TRUE;
}
else
{
// Thread creation failed, we should free the buffer.
GFree(pszCopy);
}
}
return fSuccess;
}