Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

698 lines
18 KiB

#include <windows.h>
#include <windowsx.h>
#include <stdarg.h>
#include "common.h"
#include "clipsrv.h"
#include "clipfile.h"
#include "callback.h"
#include "debugout.h"
static HANDLE hmutexClp; // for syncing open and close of clipboard
static BOOL fAnythingToRender = FALSE;
static BOOL fService = TRUE;
static BOOL fServiceStopped = FALSE;
static TCHAR szClass[] = TEXT("ClipSrvWClass");
static TCHAR szServiceName[] = TEXT("Clipbook Service");
static TCHAR wsbuf[128];
DWORD idInst = 0;
HINSTANCE hInst;
HWND hwndApp;
HSZ hszAppName = 0L;
TCHAR szTopic[MAX_TOPIC] = TEXT("ClipData");
TCHAR szServer[MAX_TOPIC] = TEXT("ClipSrv");
TCHAR szExec[MAX_EXEC] = TEXT("");
TCHAR szUpdateName[MAX_CLPSHRNAME+1] = TEXT("");
UINT cf_preview;
ShrInfo *SIHead = NULL;
static SERVICE_STATUS_HANDLE hService;
static SERVICE_STATUS srvstatus =
{
SERVICE_WIN32_OWN_PROCESS,
SERVICE_START_PENDING,
SERVICE_ACCEPT_STOP,
NO_ERROR,
0L,
1,
200
};
#if DEBUG
HKEY hkeyRoot;
HKEY hkeyClp;
#endif
void ClipSrvHandler (DWORD);
/////////////////////////////////////////////////////////////////////////
//
// "main" function... just calls StartServiceCtrlDispatcher.
//
/////////////////////////////////////////////////////////////////////////
void _cdecl main(
int argc,
char **argv)
{
SERVICE_TABLE_ENTRY srvtabl[] = {{szServiceName, ClipSrvMain},
{NULL, NULL}};
#if DEBUG
DeleteFile("C:\\CLIPSRV.OUT");
#endif
if (argv[1] && !lstrcmpi(argv[1], "-debug"))
{
fService = FALSE;
ClipSrvMain(argc, argv);
}
else
{
StartServiceCtrlDispatcher(srvtabl);
}
}
/*
* ClipSrvMain
*/
void ClipSrvMain(
DWORD argc,
LPSTR *argv)
{
MSG msg;
if (fService)
{
hService = RegisterServiceCtrlHandler(szServiceName, ClipSrvHandler);
}
if (0L != hService || FALSE == fService)
{
if (fService)
{
// Tell SCM that we're starting
SetServiceStatus(hService, &srvstatus);
}
hInst = GetModuleHandle(TEXT("CLIPSRV.EXE"));
// Perform initializations
if (InitApplication(hInst, &srvstatus))
{
if (fService)
{
// Tell SCM we've started OK
srvstatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(hService, &srvstatus);
PINFO(TEXT("Told system we're running\r\n"));
}
// Process messages
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnregisterClass(szClass, hInst);
if (fService && !fServiceStopped)
{
fServiceStopped = TRUE;
srvstatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(hService, &srvstatus);
}
if (NULL != hmutexClp)
{
CloseHandle(hmutexClp);
}
}
else
{
PERROR(TEXT("ClSrv: InitApplication failed!\r\n"));
if (fService && !fServiceStopped)
{
fServiceStopped = TRUE;
srvstatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(hService, &srvstatus);
}
}
}
}
/*
* ReportStatusToSCMgr
*
* This function is called by the ServMainFunc() and
* by the ServCtrlHandler() to update the service's status
* to the Service Control Manager.
*/
BOOL ReportStatusToSCMgr (
DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwCheckPoint,
DWORD dwWaitHint)
{
BOOL fResult;
/* disable control requests until service is started */
if (dwCurrentState == SERVICE_START_PENDING)
{
srvstatus.dwControlsAccepted = 0;
}
else
{
srvstatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
}
/* These SERVICE_STATUS members set from parameters */
srvstatus.dwCurrentState = dwCurrentState;
srvstatus.dwWin32ExitCode = dwWin32ExitCode;
srvstatus.dwCheckPoint = dwCheckPoint;
srvstatus.dwWaitHint = dwWaitHint;
/* Report status of service to Service Control Manager */
if (!(fResult = SetServiceStatus(hService,&srvstatus)))
{
/* if error occurs, stop service */
}
return fResult;
}
/*
* ClipSrvHandler
*
*
* Purpose: Acts as the HANDLER_FUNCTION for the Clipbook service.
*
* Parameters:
* fdwControl = Flags saying what action to take
*
* Returns: Void (SetServiceStatus is used to set status)
*/
void ClipSrvHandler(
DWORD fdwControl)
{
if (SERVICE_CONTROL_STOP == fdwControl)
{
PINFO(TEXT("Handler: stopping service\r\n"));
srvstatus.dwCheckPoint = 0;
srvstatus.dwCurrentState = SERVICE_STOP_PENDING;
SetServiceStatus(hService, &srvstatus);
SendMessage(hwndApp, WM_CLOSE, 0, 0);
if (!fServiceStopped) {
fServiceStopped = TRUE;
srvstatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(hService, &srvstatus);
}
PINFO(TEXT("Handler: Service stopped\r\n"));
}
else
{
// Unhandled control request.. just keep running.
srvstatus.dwCurrentState = SERVICE_RUNNING;
srvstatus.dwWin32ExitCode = NO_ERROR;
SetServiceStatus(hService, &srvstatus);
}
return;
}
/*
* InitApplication
*
*
* Purpose: Application initialization, including creation of a window
* to do DDE with, getting settings out of the registry, and starting
* up DDE.
*
* Parameters:
* hInstance - Application instance.
* psrvstatus - Pointer to a SERVICE_STATUS struct. We update the
* dwCheckPoint member of this struct and call SetServiceStatus,
* so the system knows that we didn't die.
*
* Returns: True on OK, false on fail.
*/
BOOL InitApplication(
HINSTANCE hInstance,
SERVICE_STATUS *psrvstatus)
{
WNDCLASS wc;
#if DEBUG
DWORD dwKeyStatus;
#endif
HWINSTA hwinsta;
wc.style = 0L;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CLIPSRV));
wc.hCursor = NULL;
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = TEXT("ClipSrvWClass");
if (!RegisterClass(&wc))
{
PERROR(TEXT("Couldn't register wclass\r\n"));
return FALSE;
}
/*
* We are now connected to the appropriate service windowstation
* and desktop. In order to get stuff from clipbook, we need to
* switch our process over to use the interactive user's
* clipboard. Verify that we have access to do this.
*/
hwinsta = OpenWindowStation("WinSta0", FALSE,
WINSTA_ACCESSCLIPBOARD | WINSTA_ACCESSGLOBALATOMS);
if (hwinsta == NULL) {
PERROR(TEXT("Couldn't open windowstation WinSta0\r\n"));
return FALSE;
}
SetProcessWindowStation(hwinsta);
psrvstatus->dwCheckPoint++;
hmutexClp = CreateMutex(NULL, FALSE, SZMUTEXCLP);
hwndApp = CreateWindow(TEXT("ClipSrvWClass"),
TEXT("Hidden Data Server"),
WS_POPUP,
CW_USEDEFAULT,
CW_USEDEFAULT,
400,
200,
NULL,
NULL,
hInstance,
NULL
);
if (!hwndApp)
{
PERROR(TEXT("No window created\r\n"));
return FALSE;
}
psrvstatus->dwCheckPoint++;
#if DEBUG
if (ERROR_SUCCESS != RegCreateKeyEx (HKEY_CURRENT_USER,
szClipviewRoot,
0L,
szRegClass,
REG_OPTION_NON_VOLATILE,
KEY_QUERY_VALUE, NULL,
&hkeyClp,
&dwKeyStatus)
&&
ERROR_SUCCESS != RegOpenKeyEx (HKEY_CURRENT_USER,
szClipviewRoot,
0,
KEY_QUERY_VALUE,
&hkeyClp))
{
DebugLevel = 2;
PINFO(TEXT("Clipsrv: Could not get root key\r\n"));
}
else
{
DWORD iSize = sizeof(DebugLevel);
RegQueryValueEx (hkeyClp,
szDebug,
NULL,
NULL,
(LPBYTE)&DebugLevel,
&iSize);
RegCloseKey (hkeyClp);
}
if (DebugLevel > 0)
{
ShowWindow(hwndApp, SW_SHOWMINNOACTIVE );
}
#endif
if (DdeInitialize ((LPDWORD)&idInst,
(PFNCALLBACK)DdeCallback,
APPCMD_FILTERINITS,
0L))
{
PERROR(TEXT("Couldn't initialize DDE\r\n"));
return FALSE;
}
PINFO(TEXT("DdeInit OK...\r\n"));
psrvstatus->dwCheckPoint++;
if (fService)
{
SetServiceStatus(hService, psrvstatus);
}
Hszize();
DdeNameService(idInst, hszAppName, 0L, DNS_REGISTER);
InitShares();
return TRUE;
}
/*
* MainWndProc
*/
LRESULT CALLBACK MainWndProc(
HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
fAnythingToRender = FALSE;
cf_preview = RegisterClipboardFormat (SZPREVNAME);
if (fService)
{
// Let the SCP that started us know that we're making progress
srvstatus.dwCheckPoint++;
SetServiceStatus(hService, &srvstatus);
}
PINFO(TEXT("Creating ClSrv window\r\n"));
break;
case WM_DESTROYCLIPBOARD:
/* Prevent unnecessary file I/O when getting a WM_RENDERALLFORMATS */
fAnythingToRender = FALSE;
break;
case WM_RENDERALLFORMATS:
PINFO(TEXT("ClSrv\\WM_RNDRALL rcvd\r\n"));
return (LRESULT)RenderAllFromFile(szSaveFileName);
break;
case WM_RENDERFORMAT:
SetClipboardData((UINT)wParam, RenderFormatFromFile(szSaveFileName, (WORD)wParam));
break;
case WM_QUERYOPEN:
return FALSE;
case WM_DESTROY:
PINFO(TEXT("sTOPPING...\r\n"));
CleanUpShares();
DdeNameService(idInst, 0L, 0L, DNS_UNREGISTER);
UnHszize();
DdeUninitialize(idInst);
if (fService)
{
// Tell SCP we're stopping
srvstatus.dwCheckPoint++;
SetServiceStatus(hService, &srvstatus);
}
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hwnd, message, wParam, lParam));
}
return 0L;
}
/*
* RenderRawFormatToDDE
*/
HDDEDATA RenderRawFormatToDDE(
FORMATHEADER *pfmthdr,
HANDLE fh )
{
HDDEDATA hDDE;
LPBYTE lpDDE;
DWORD cbData;
DWORD dwBytesRead;
BOOL fPrivate = FALSE, fMetafile = FALSE, fBitmap = FALSE;
PINFO(TEXT("ClSrv\\RndrRawFmtToDDE:"));
// Note that complex-data formats are sent under a private
// format instead.
if (PRIVATE_FORMAT(pfmthdr->FormatID )
|| pfmthdr->FormatID == CF_BITMAP
|| pfmthdr->FormatID == CF_METAFILEPICT
|| pfmthdr->FormatID == CF_PALETTE
|| pfmthdr->FormatID == CF_DIB
|| pfmthdr->FormatID == CF_ENHMETAFILE
)
{
fPrivate = TRUE;
if (pfmthdr->FormatID == CF_BITMAP)
{
fBitmap = TRUE;
}
else if (pfmthdr->FormatID == CF_METAFILEPICT)
{
fMetafile = TRUE;
}
pfmthdr->FormatID = RegisterClipboardFormatW(pfmthdr->Name);
}
PINFO(TEXT("rendering format %ws as %x\n\r"), (LPTSTR)pfmthdr->Name, pfmthdr->FormatID );
#ifdef CACHEPREVIEWS
if ( pfmthdr->FormatID == cf_preview )
PINFO(TEXT("making APPOWNED data\n\r"));
#endif
if (!(hDDE = DdeCreateDataHandle (idInst,
NULL,
pfmthdr->DataLen,
0L,
hszAppName,
pfmthdr->FormatID,
#ifdef CACHEPREVIEWS
pfmthdr->FormatID == cf_preview ? HDATA_APPOWNED : 0
#else
0
#endif
)))
{
PERROR(TEXT("Couldn't createdata handle\r\n"));
goto done;
}
if ( !(lpDDE = DdeAccessData ( hDDE, &cbData )) )
{
PERROR(TEXT("Couldn't access handle\r\n"));
DdeFreeDataHandle(hDDE);
hDDE = 0L;
goto done;
}
if (~0 == SetFilePointer(fh, pfmthdr->DataOffset, NULL, FILE_BEGIN))
{
PERROR(TEXT("Couldn't set file pointer\r\n"));
DdeUnaccessData(hDDE);
DdeFreeDataHandle(hDDE);
hDDE = 0L;
goto done;
}
ReadFile(fh, lpDDE, pfmthdr->DataLen, &dwBytesRead, NULL);
if (dwBytesRead != pfmthdr->DataLen)
{
// Error in reading the file
DdeUnaccessData(hDDE);
DdeFreeDataHandle(hDDE);
PERROR(TEXT("Error reading file: %ld from lread\n\r"),
dwBytesRead);
hDDE = 0L;
goto done;
}
// This code packs CF_METAFILEPICT and CF_BITMAP structs to WFW-type
// structs. It may lose extents for very large bitmaps and metafiles
// when going from NT to NT. Main symptom would be "Moved a metafile
// across clipbook and it suddenly grew way outside its bounds".
if (fMetafile)
{
WIN31METAFILEPICT w31mfp;
unsigned uNewSize;
HDDEDATA hDDETmp;
uNewSize = pfmthdr->DataLen + sizeof(WIN31METAFILEPICT) -
sizeof(METAFILEPICT);
// Have to make a smaller data handle now
hDDETmp = hDDE;
hDDE = DdeCreateDataHandle(idInst, NULL, uNewSize, 0L,
hszAppName, pfmthdr->FormatID, 0);
w31mfp.mm = (WORD)((METAFILEPICT *)lpDDE)->mm;
w31mfp.xExt = (WORD)((METAFILEPICT *)lpDDE)->xExt;
w31mfp.yExt = (WORD)((METAFILEPICT *)lpDDE)->yExt;
// Place oldmetafilepict and data in new DDE block
DdeAddData(hDDE, (LPTSTR)&w31mfp, sizeof(WIN31METAFILEPICT), 0L);
DdeAddData(hDDE, lpDDE + sizeof(METAFILEPICT),
uNewSize - sizeof(WIN31METAFILEPICT),
sizeof(WIN31METAFILEPICT));
// Drop old handle
DdeUnaccessData(hDDETmp);
DdeFreeDataHandle(hDDETmp);
// We came in with hDDE accessed
lpDDE = DdeAccessData(hDDE, &cbData);
}
else if (fBitmap)
{
WIN31BITMAP w31bm;
unsigned uNewSize;
HDDEDATA hDDETmp;
uNewSize = pfmthdr->DataLen + sizeof(WIN31BITMAP) -
sizeof(BITMAP);
// Have to make a smaller data handle now
hDDETmp = hDDE;
hDDE = DdeCreateDataHandle(idInst, NULL, uNewSize, 0L,
hszAppName, pfmthdr->FormatID, 0);
w31bm.bmType = (WORD)((BITMAP *)lpDDE)->bmType;
w31bm.bmWidth = (WORD)((BITMAP *)lpDDE)->bmWidth;
w31bm.bmHeight = (WORD)((BITMAP *)lpDDE)->bmHeight;
w31bm.bmWidthBytes = (WORD)((BITMAP *)lpDDE)->bmWidthBytes;
w31bm.bmPlanes = (BYTE)((BITMAP *)lpDDE)->bmPlanes;
w31bm.bmBitsPixel = (BYTE)((BITMAP *)lpDDE)->bmBitsPixel;
// Place old-style bitmap header and data in DDE block
DdeAddData(hDDE, (LPTSTR)&w31bm, sizeof(WIN31BITMAP), 0L);
DdeAddData(hDDE, lpDDE + sizeof(BITMAP),
uNewSize - sizeof(WIN31BITMAP),
sizeof(WIN31BITMAP));
// Drop old handle
DdeUnaccessData(hDDETmp);
DdeFreeDataHandle(hDDETmp);
// We came in with hDDE accessed
lpDDE = DdeAccessData(hDDE, &cbData);
}
DdeUnaccessData(hDDE);
done:
PINFO("Ret %lx\r\n", hDDE);
return(hDDE);
}
/*
* SyncOpenClipboard
*/
BOOL SyncOpenClipboard(
HWND hwnd)
{
BOOL fOK;
PINFO(TEXT("\r\nClipSrv: Opening Clipboard\r\n"));
WaitForSingleObject (hmutexClp, INFINITE);
fOK = OpenClipboard (hwnd);
if (!fOK)
{
ReleaseMutex (hmutexClp);
}
return fOK;
}
/*
* SyncCloseClipboard
*/
BOOL SyncCloseClipboard(void)
{
BOOL fOK;
PINFO(TEXT("\r\nClipSrv: Closing Clipboard\r\n"));
fOK = CloseClipboard ();
ReleaseMutex (hmutexClp);
return fOK;
}