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.

2161 lines
66 KiB

  1. /*****************************************************************************
  2. C L I P B O A R D
  3. Name: clipbrk.c
  4. Date: 21-Jan-1994
  5. Creator: Unknown
  6. Description:
  7. This is the main clipbrd module. It has the program entry point,
  8. the windows procedures and some major supporting functions.
  9. *****************************************************************************/
  10. #define WIN31
  11. #define STRICT
  12. #include <windows.h>
  13. #include <windowsx.h>
  14. #include <commctrl.h>
  15. #include <lm.h>
  16. #include <nddeapi.h>
  17. #include <nddeagnt.h>
  18. #include <stdio.h>
  19. #include <htmlhelp.h>
  20. #include <strsafe.h>
  21. #include "common.h"
  22. #include "clipbook.h"
  23. #include "clipbrd.h"
  24. #include "dialogs.h"
  25. #include "clipdsp.h"
  26. #include "cvutil.h"
  27. #include "cvinit.h"
  28. #include "auditchk.h"
  29. #include "callback.h"
  30. #include "debugout.h"
  31. #include "helpids.h"
  32. #include "initmenu.h"
  33. #include "cvcomman.h"
  34. #include "clipfile.h"
  35. #include "strtok.h"
  36. #include "security.h"
  37. #ifndef UNICODE_CHARSET
  38. #define UNICODE_CHARSET 1
  39. #endif
  40. //
  41. // return code of OnPaint
  42. //
  43. #define ONPAINT_FAIL 0
  44. #define ONPAINT_SUCCESS 1
  45. #define ONPAINT_NOCLIPBRD 2
  46. typedef UINT (WINAPI *WNETCALL)(HWND, LPSTR, LPSTR, WORD, DWORD );
  47. // Static data
  48. static HHOOK hMsgFilterHook;
  49. // Stuff for dealing with minimized MDI children
  50. static HCURSOR hcurClipbook;
  51. static HCURSOR hcurClipbrd;
  52. static HCURSOR hcurRemote;
  53. static BOOL fClpOpen;
  54. HANDLE hmutexClp; // clipboard mutex
  55. HANDLE hXacting; // transaction event
  56. HANDLE hmodNetDriver;
  57. HICON hicClipbrd;
  58. HICON hicClipbook;
  59. HICON hicRemote;
  60. HICON hicLock; // Icon for Lock on thumbnail bitmaps
  61. HFONT hfontUni; // Handle for Unicode font, if it exists
  62. // Application-wide flags
  63. BOOL fStatus; // status bar shown?
  64. BOOL fToolBar; // tool bar shown?
  65. BOOL fShareEnabled; // sharing allowed in system.ini?
  66. BOOL fNetDDEActive = TRUE; // NetDDE detected?
  67. BOOL fAppLockedState = FALSE; // app UI locked (see LockApp())
  68. BOOL fClipboardNeedsPainting = FALSE; // indicates deferred clp paint
  69. BOOL fSharePreference; // shared checked on paste?
  70. BOOL fNeedToTileWindows = FALSE; // need to tile windows on size
  71. BOOL fAppShuttingDown = FALSE; // in process of closing
  72. BOOL fFillingClpFromDde = FALSE; // in process of adding clp formats
  73. BOOL fAuditEnabled;
  74. HWND hwndNextViewer = NULL; // for clpbrd viewer chain
  75. HWND hwndDummy; // used as dummy SetCapture target
  76. // special case clipboard formats
  77. UINT cf_bitmap; // we send/receive these in private 'packed' format
  78. UINT cf_metafilepict;
  79. UINT cf_palette;
  80. UINT cf_preview; // PREVBMPSIZxPREVBMPSIZ preview bitmap private format
  81. // these are formats that contain untranslated copies of link and objlink data
  82. UINT cf_objectlinkcopy;
  83. UINT cf_objectlink;
  84. UINT cf_linkcopy;
  85. UINT cf_link;
  86. // DDEML
  87. // These are effective constants created once and destroyed when we die
  88. HSZ hszSystem;
  89. HSZ hszTopics;
  90. HSZ hszDataSrv;
  91. HSZ hszFormatList;
  92. HSZ hszClpBookShare;
  93. DWORD idInst = 0;
  94. DWORD dwCurrentHelpId = 0L;
  95. // instance proc from MSGF_DDEMGR filter
  96. WINDOWPLACEMENT Wpl;
  97. HOOKPROC lpMsgFilterProc;
  98. HINSTANCE hInst;
  99. HACCEL hAccel;
  100. HFONT hOldFont;
  101. HFONT hFontStatus;
  102. HFONT hFontPreview;
  103. HWND hwndActiveChild = 0; // this handle identifies the currently active MDI window
  104. PMDIINFO pActiveMDI = NULL; // this pointer points to the MDI info struct of the
  105. // active MDI window IT SHOULD ALWAYS ==
  106. // GETMDIINFO(hwndActiveChild)
  107. HWND hwndClpbrd = 0; // this handle identifies the clipboard window
  108. HWND hwndLocal = 0; // this handle identifies the local clipbook window
  109. HWND hwndClpOwner = 0; // this handle identifies the clipboard owning MDI child (if any)
  110. HWND hwndMDIClient; // handle to MDI Client window
  111. HWND hwndApp; // global app window
  112. HDC hBtnDC; // memory DC used for owner draw stuff
  113. HBITMAP hOldBitmap;
  114. HBITMAP hPreviewBmp;
  115. HBITMAP hPgUpBmp;
  116. HBITMAP hPgDnBmp;
  117. HBITMAP hPgUpDBmp;
  118. HBITMAP hPgDnDBmp;
  119. int dyStatus; // height of status bar
  120. int dyButtonBar; // height of button bar
  121. int dyPrevFont; // height of listbox font - height+external
  122. TCHAR szHelpFile[] = TEXT("clipbrd.hlp");
  123. TCHAR szChmHelpFile[] = TEXT("clipbrd.chm");
  124. TCHAR szClipBookClass[] = TEXT("ClipBookWClass"); // frame window class
  125. TCHAR szChild[] = TEXT("CVchild"); // Class name for MDI window
  126. TCHAR szDummy[] = TEXT("CVdummy"); // class name of hidden dummy window
  127. TCHAR szNDDEcode[] = TEXT("NDDE$");
  128. TCHAR szNDDEcode1[] = TEXT("NDDE$0001");
  129. TCHAR szClpBookShare[] = TEXT("CLPBK$");
  130. // localized strings
  131. TCHAR szHelv[SMLRCBUF]; // status line font
  132. TCHAR szAppName[SMLRCBUF];
  133. TCHAR szLocalClpBk[SMLRCBUF];
  134. TCHAR szSysClpBrd[SMLRCBUF];
  135. TCHAR szDataUnavail[BIGRCBUF];
  136. TCHAR szReadingItem[BIGRCBUF];
  137. TCHAR szViewHelpFmt[BIGRCBUF];
  138. TCHAR szActivateFmt[BIGRCBUF];
  139. TCHAR szRendering[BIGRCBUF];
  140. TCHAR szDefaultFormat[BIGRCBUF];
  141. TCHAR szGettingData[BIGRCBUF];
  142. TCHAR szEstablishingConn[BIGRCBUF];
  143. TCHAR szClipBookOnFmt[BIGRCBUF];
  144. TCHAR szPageFmt[SMLRCBUF];
  145. TCHAR szPageFmtPl[SMLRCBUF];
  146. TCHAR szPageOfPageFmt[SMLRCBUF];
  147. TCHAR szDelete[SMLRCBUF];
  148. TCHAR szDeleteConfirmFmt[SMLRCBUF];
  149. TCHAR szFileFilter[BIGRCBUF];
  150. TCHAR *szFilter;
  151. // Registry key strings
  152. TCHAR szRoot[128];
  153. TCHAR szPref[] = TEXT("Preferences");
  154. TCHAR szConn[] = TEXT("Connections");
  155. TCHAR szStatusbar[] = TEXT("StatusBar");
  156. TCHAR szToolbar[] = TEXT("ToolBar");
  157. TCHAR szShPref[] = TEXT("AutoShare");
  158. TCHAR szEnableShr[] = TEXT("EnableShare");
  159. TCHAR szDefView[] = TEXT("DefView");
  160. #if DEBUG
  161. TCHAR szDebug[] = TEXT("Debug");
  162. #endif
  163. TCHAR szNull[] = TEXT("");
  164. HKEY hkeyRoot;
  165. TCHAR szBuf[SZBUFSIZ];
  166. TCHAR szBuf2[SZBUFSIZ];
  167. TCHAR szConvPartner[128]; // bigger than max server name
  168. TCHAR szKeepAs[ MAX_NDDESHARENAME + 2 ];
  169. static BOOL InitApplication (HINSTANCE hInstance);
  170. static BOOL InitInstance (HINSTANCE hInstance, int nCmdShow);
  171. static VOID StripCharRange (TCHAR *s, char lower, char upper);
  172. static VOID SendMessageToKids (WORD msg, WPARAM wParam, LPARAM lParam);
  173. static VOID StripAcceleratorKey (TCHAR *s);
  174. ////////////////////// functions //////////////////////////////////
  175. int WINAPI WinMain(
  176. HINSTANCE hInstance,
  177. HINSTANCE hPrevInstance,
  178. LPSTR lpCmdLine,
  179. int nCmdShow)
  180. {
  181. MSG msg;
  182. OFSTRUCT of;
  183. PMDIINFO pMDI;
  184. #if DEBUG
  185. DebugLevel = 2;
  186. #endif
  187. LoadString(hInstance, IDS_APPNAME, szAppName, SMLRCBUF);
  188. // Only one instance is supported
  189. // hPrevInstance always == null under NT, so we have to rely on FWin.
  190. if (hwndApp = FindWindow(szClipBookClass, NULL))
  191. {
  192. PINFO(TEXT("Found previous instance\r\n"));
  193. if (IsIconic(hwndApp))
  194. {
  195. ShowWindow(hwndApp, SW_RESTORE);
  196. SetForegroundWindow(hwndApp);
  197. }
  198. else
  199. {
  200. SetForegroundWindow(hwndApp);
  201. }
  202. return FALSE;
  203. }
  204. if (!InitApplication(hInstance))
  205. {
  206. PERROR(TEXT("InitApp fail\r\n"));
  207. return (FALSE);
  208. }
  209. if (!InitInstance(hInstance, nCmdShow ))
  210. {
  211. PERROR(TEXT("InitInstance fail\r\n"));
  212. return (FALSE);
  213. }
  214. UpdateWindow ( hwndApp );
  215. // if we were started with the name of a file on the command line,
  216. // attempt to load the .clp file via an open dde execute
  217. if (OpenFile (lpCmdLine, &of, OF_EXIST) != HFILE_ERROR )
  218. {
  219. if ( ClearClipboard(hwndApp) )
  220. {
  221. #ifdef UNICODE
  222. TCHAR *ptch;
  223. ptch = (TCHAR *)LocalAlloc (LPTR, (lstrlenA(lpCmdLine) + 1) * sizeof(TCHAR));
  224. MultiByteToWideChar (CP_ACP,
  225. MB_PRECOMPOSED,
  226. lpCmdLine,
  227. -1,
  228. ptch,
  229. lstrlenA(lpCmdLine)+1);
  230. lstrcat(lstrcpy(szBuf, SZCMD_OPEN),ptch);
  231. #else
  232. StringCchCopy(szBuf, SZBUFSIZ, SZCMD_OPEN),
  233. StringCchCat (szBuf, SZBUFSIZ, lpCmdLine);
  234. #endif
  235. if (pMDI = GETMDIINFO(hwndLocal))
  236. {
  237. MySyncXact ((LPBYTE)szBuf,
  238. lstrlen(szBuf) +1,
  239. pMDI->hExeConv,
  240. 0L,
  241. CF_TEXT,
  242. XTYP_EXECUTE,
  243. SHORT_SYNC_TIMEOUT,
  244. NULL );
  245. }
  246. InitializeMenu ( GetMenu(hwndApp) );
  247. }
  248. }
  249. while (GetMessage (&msg, NULL, 0, 0))
  250. {
  251. if (!TranslateMDISysAccel (hwndMDIClient, &msg) &&
  252. (hAccel? !TranslateAccelerator(hwndApp, hAccel, &msg): 1))
  253. {
  254. TranslateMessage (&msg);
  255. DispatchMessage (&msg);
  256. }
  257. }
  258. // Clear the mutex
  259. CloseHandle(hmutexClp);
  260. // free up our HSZ 'constants'
  261. DdeFreeStringHandle(idInst, hszTopics);
  262. DdeFreeStringHandle(idInst, hszFormatList );
  263. DdeFreeStringHandle(idInst, hszSystem);
  264. DdeFreeStringHandle(idInst, hszDataSrv);
  265. DdeFreeStringHandle(idInst, hszClpBookShare );
  266. DdeFreeStringHandle(idInst, hszErrorRequest);
  267. // Free icons & cursors
  268. DestroyIcon(hicClipbrd);
  269. DestroyIcon(hicClipbook);
  270. DestroyIcon(hicRemote);
  271. DestroyIcon(hicLock);
  272. DestroyCursor(hcurClipbrd);
  273. DestroyCursor(hcurClipbook);
  274. DestroyCursor(hcurRemote);
  275. DdeUninitialize(idInst);
  276. UnhookWindowsHookEx(hMsgFilterHook);
  277. return (int)(msg.wParam);
  278. }
  279. static BOOL InitApplication (HINSTANCE hInstance)
  280. {
  281. WNDCLASS wc;
  282. // Register the frame window
  283. wc.style = 0;
  284. wc.lpfnWndProc = FrameWndProc;
  285. wc.cbClsExtra = 0;
  286. wc.cbWndExtra = 0;
  287. wc.hInstance = hInstance;
  288. wc.hIcon = LoadIcon ( hInstance, MAKEINTRESOURCE(IDFRAMEICON) );
  289. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  290. wc.hbrBackground = NULL; // will paint whole client area
  291. wc.lpszMenuName = MAKEINTRESOURCE(IDCVMENU);
  292. wc.lpszClassName = szClipBookClass;
  293. if (0 == RegisterClass(&wc))
  294. {
  295. return FALSE;
  296. }
  297. // Register the MDI child class
  298. wc.lpfnWndProc = ChildWndProc;
  299. wc.hIcon = NULL;
  300. wc.lpszMenuName = NULL;
  301. wc.cbWndExtra = CBWNDEXTRA;
  302. wc.lpszClassName = szChild;
  303. wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
  304. wc.style = CS_DBLCLKS;
  305. if (0 == RegisterClass(&wc))
  306. return FALSE;
  307. // register dummy window for SetCapture target
  308. wc.lpfnWndProc = DefWindowProc;
  309. wc.hIcon = NULL;
  310. wc.lpszMenuName = NULL;
  311. wc.cbWndExtra = 0;
  312. wc.lpszClassName = szDummy;
  313. wc.style = 0;
  314. if (0 == RegisterClass(&wc))
  315. return FALSE;
  316. return TRUE;
  317. }
  318. /*
  319. * SetupForFloatingProfile
  320. */
  321. static void SetupForFloatingProfile ()
  322. {
  323. TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH+3] = TEXT("\\\\");
  324. DWORD cbName = sizeof(szComputerName) + 1;
  325. NDDESHAREINFO ShareInfo =
  326. {
  327. 1, // revision
  328. szClpBookShare,
  329. SHARE_TYPE_STATIC,
  330. TEXT("ClipSrv|System\0\0"),
  331. TRUE, // shared
  332. TRUE, // a service
  333. FALSE, // cannot be started
  334. SW_SHOWNORMAL,
  335. {0,0}, // mod id
  336. 0, // no item list
  337. TEXT("")
  338. };
  339. START_NETDDE_SERVICES(hwndApp);
  340. GetComputerName (&szComputerName[2], &cbName);
  341. NDdeShareAdd (szComputerName,
  342. 2,
  343. NULL,
  344. (LPBYTE)&ShareInfo,
  345. sizeof (ShareInfo));
  346. NDdeSetTrustedShare (szComputerName,
  347. szClpBookShare,
  348. NDDE_TRUST_SHARE_START |
  349. NDDE_TRUST_SHARE_INIT);
  350. }
  351. BOOL InitInstance(
  352. HINSTANCE hInstance,
  353. int nCmdShow)
  354. {
  355. LOGFONT UniFont;
  356. DWORD dwKeyStatus;
  357. HMENU hFileMenu;
  358. SC_HANDLE hsc;
  359. SC_HANDLE hsrvWksta;
  360. SERVICE_STATUS ss;
  361. UINT ddeErr;
  362. // Stuff used to make the local server's name, "\\<computername>\NDDE$"
  363. TCHAR atchSrvName[MAX_COMPUTERNAME_LENGTH + 9];
  364. DWORD dwSize;
  365. static TCHAR szBuffer[256] = TEXT("\0");
  366. int cch, i;
  367. LCID lcid = GetThreadLocale();
  368. hInst = hInstance;
  369. hmutexClp = CreateMutex(NULL, FALSE, SZMUTEXCLP);
  370. hXacting = CreateEvent (NULL, FALSE, TRUE, NULL);
  371. hAccel = LoadAccelerators(hInstance, (LPCTSTR)MAKEINTRESOURCE(IDACCELERATORS));
  372. if (NULL == hAccel)
  373. {
  374. PERROR(TEXT("error loading accelerator table\n\r"));
  375. #ifndef DEBUG
  376. return FALSE;
  377. #endif
  378. }
  379. // Load cursors for dragging MDI children
  380. hcurClipbook = LoadCursor (hInst, (LPCTSTR)MAKEINTRESOURCE(IDC_CLIPBOOK));
  381. hcurClipbrd = LoadCursor (hInst, (LPCTSTR)MAKEINTRESOURCE(IDC_CLIPBRD));
  382. hcurRemote = LoadCursor (hInst, (LPCTSTR)MAKEINTRESOURCE(IDC_REMOTE));
  383. // Load icons for MDI children
  384. hicClipbook = LoadIcon (hInst, (LPCTSTR)MAKEINTRESOURCE(IDI_CLIPBOOK));
  385. hicClipbrd = LoadIcon (hInst, (LPCTSTR)MAKEINTRESOURCE(IDI_CLIPBRD));
  386. hicRemote = LoadIcon (hInst, (LPCTSTR)MAKEINTRESOURCE(IDI_REMOTE));
  387. // Load Lock icon
  388. hicLock = LoadIcon ( hInst, MAKEINTRESOURCE(IDLOCKICON));
  389. // Load the Unicode font, for displaying Unicode text.
  390. GetObject (GetStockObject(SYSTEM_FONT), sizeof(LOGFONT), (LPBYTE)&UniFont);
  391. if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_JAPANESE ||
  392. PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_CHINESE ||
  393. PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_KOREAN)
  394. {
  395. UniFont.lfCharSet = ANSI_CHARSET;
  396. StringCchCopy(UniFont.lfFaceName, LF_FACESIZE, TEXT("Lucida Sans Unicode"));
  397. }
  398. else
  399. {
  400. UniFont.lfCharSet = UNICODE_CHARSET;
  401. StringCchCopy(UniFont.lfFaceName, LF_FACESIZE, TEXT("Lucida Sans Unicode Regular"));
  402. }
  403. hfontUni = CreateFontIndirect(&UniFont);
  404. if (hfontUni == NULL)
  405. {
  406. hfontUni = (HFONT)GetStockObject(SYSTEM_FONT);
  407. }
  408. LoadIntlStrings();
  409. if(!szBuffer[0])
  410. {
  411. cch = LoadString( hInst, IDS_FILTERTEXT, szBuffer, sizeof(szBuffer) );
  412. for( i = 0; i <= cch; i++ )
  413. {
  414. szBuffer[i] = (szBuffer[i] == TEXT('\1')) ? TEXT('\0') : szBuffer[i];
  415. }
  416. szFilter = szBuffer;
  417. }
  418. // initialize variables in clipdsp.c
  419. fOwnerDisplay = FALSE;
  420. // initialize DDEML
  421. ddeErr = DdeInitialize (&idInst,(PFNCALLBACK)DdeCallback,APPCLASS_STANDARD, 0L);
  422. if (DMLERR_NO_ERROR != ddeErr)
  423. {
  424. PERROR(TEXT("The DDEML did not initialize\n\r"));
  425. DdeMessageBox (hInst, NULL, ddeErr, IDS_APPNAME, MB_OK|MB_ICONSTOP);
  426. return FALSE;
  427. }
  428. // create our hsz constants
  429. atchSrvName[0] = atchSrvName[1] = TEXT('\\');
  430. dwSize = MAX_COMPUTERNAME_LENGTH+1;
  431. GetComputerName(atchSrvName + 2, &dwSize);
  432. StringCchCat(atchSrvName, MAX_COMPUTERNAME_LENGTH + 9, TEXT("\\NDDE$"));
  433. hszDataSrv = DdeCreateStringHandleA(idInst, atchSrvName, CP_WINANSI);
  434. hszSystem = DdeCreateStringHandleA(idInst, "CLPBK$", CP_WINANSI);
  435. hszTopics = DdeCreateStringHandleA(idInst, SZDDESYS_ITEM_TOPICS, CP_WINANSI);
  436. hszFormatList = DdeCreateStringHandleA(idInst, SZ_FORMAT_LIST, CP_WINANSI);
  437. hszClpBookShare = DdeCreateStringHandleA(idInst, szClpBookShare, CP_WINANSI);
  438. hszErrorRequest = DdeCreateStringHandleA(idInst, SZ_ERR_REQUEST, CP_WINANSI);
  439. if (DdeGetLastError(idInst) != DMLERR_NO_ERROR )
  440. {
  441. PERROR(TEXT("DDEML error during init\n\r"));
  442. return FALSE;
  443. }
  444. // We set this hook up so that we can catch the MSGF_DDEMGR message
  445. // which is called when DDEML is in a modal loop during synchronous
  446. // transaction processing.
  447. lpMsgFilterProc = (HOOKPROC)MyMsgFilterProc;
  448. hMsgFilterHook = SetWindowsHookEx (WH_MSGFILTER,
  449. lpMsgFilterProc,
  450. hInst,
  451. GetCurrentThreadId());
  452. if (NULL == hMsgFilterHook)
  453. {
  454. PERROR(TEXT("SetWindowsHook failed\n\r"));
  455. return FALSE;
  456. }
  457. // get preference flags
  458. LoadString(hInst, IDS_CLPBKKEY, szRoot, sizeof(szRoot));
  459. if (ERROR_SUCCESS != RegCreateKeyEx (HKEY_CURRENT_USER,
  460. szRoot,
  461. 0L,
  462. NULL,
  463. REG_OPTION_NON_VOLATILE,
  464. KEY_QUERY_VALUE |
  465. KEY_SET_VALUE |
  466. KEY_ENUMERATE_SUB_KEYS,
  467. NULL,
  468. &hkeyRoot,
  469. &dwKeyStatus))
  470. {
  471. PERROR(TEXT("Could not set up root key\r\n"));
  472. fStatus = TRUE;
  473. fToolBar = TRUE;
  474. fSharePreference = TRUE;
  475. fShareEnabled = FALSE;
  476. }
  477. else
  478. {
  479. DWORD iSize = sizeof(fStatus);
  480. PINFO (TEXT("Root key created. Key Status %ld."),dwKeyStatus);
  481. if (ERROR_SUCCESS != RegQueryValueEx (hkeyRoot, szStatusbar,
  482. NULL, NULL, (LPBYTE)&fStatus, &iSize))
  483. {
  484. fStatus = TRUE;
  485. }
  486. iSize = sizeof(fToolBar);
  487. if (ERROR_SUCCESS != RegQueryValueEx (hkeyRoot, szToolbar,
  488. NULL, NULL, (LPBYTE)&fToolBar, &iSize))
  489. {
  490. fToolBar = TRUE;
  491. }
  492. iSize = sizeof(fSharePreference);
  493. if (ERROR_SUCCESS != RegQueryValueEx (hkeyRoot, szShPref,
  494. NULL, NULL, (LPBYTE)&fSharePreference, &iSize))
  495. {
  496. fSharePreference = FALSE;
  497. }
  498. #if DEBUG
  499. iSize = sizeof(DebugLevel);
  500. if (ERROR_SUCCESS != RegQueryValueEx (hkeyRoot, szDebug, NULL, NULL,
  501. (LPBYTE)&DebugLevel, &iSize))
  502. {
  503. DebugLevel = 2;
  504. }
  505. #endif
  506. iSize = sizeof(fShareEnabled);
  507. if (ERROR_SUCCESS != RegQueryValueEx (hkeyRoot, szEnableShr,
  508. NULL, NULL, (LPBYTE)&fShareEnabled, &iSize))
  509. {
  510. fShareEnabled = TRUE;
  511. }
  512. }
  513. // Figure out if NetBIOS is active or not, thus if we can net connect
  514. fNetDDEActive = FALSE;
  515. hsc = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
  516. if (NULL != hsc)
  517. {
  518. hsrvWksta = OpenService(hsc, "LanmanWorkstation", SERVICE_QUERY_STATUS);
  519. if (NULL != hsrvWksta)
  520. {
  521. if (QueryServiceStatus(hsrvWksta, &ss))
  522. {
  523. if (ss.dwCurrentState == SERVICE_RUNNING)
  524. {
  525. fNetDDEActive = TRUE;
  526. }
  527. }
  528. CloseServiceHandle(hsrvWksta);
  529. }
  530. CloseServiceHandle(hsc);
  531. }
  532. else
  533. {
  534. PERROR(TEXT("Couldn't open SC mgr\r\n"));
  535. }
  536. // override if not on a domain
  537. {
  538. LPWSTR pszDomain;
  539. NETSETUP_JOIN_STATUS nsjs;
  540. if (NERR_Success == NetGetJoinInformation(NULL, &pszDomain, &nsjs))
  541. {
  542. if ( nsjs != NetSetupDomainName)
  543. fNetDDEActive = FALSE;
  544. NetApiBufferFree(pszDomain);
  545. }
  546. }
  547. fAuditEnabled = AuditPrivilege(AUDIT_PRIVILEGE_CHECK);
  548. // Create main window
  549. if ( !( hwndApp = CreateWindow (szClipBookClass,
  550. szAppName,
  551. WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
  552. CW_USEDEFAULT,
  553. CW_USEDEFAULT,
  554. CW_USEDEFAULT,
  555. CW_USEDEFAULT,
  556. NULL,
  557. NULL,
  558. hInstance,
  559. NULL)))
  560. {
  561. PERROR(TEXT("CreateWindow failed!\r\n"));
  562. return FALSE;
  563. }
  564. SetupForFloatingProfile ();
  565. // Get the handle to the Display popup menu for adding format entries
  566. hDispMenu = GetSubMenu( GetMenu(hwndApp), DISPLAY_MENU_INDEX);
  567. hFileMenu = GetSubMenu(GetMenu(hwndApp), 0);
  568. // get rid of share menu entries?
  569. if ( !fShareEnabled )
  570. {
  571. EnableMenuItem ( hFileMenu, IDM_SHARE, MF_BYCOMMAND | MF_GRAYED);
  572. EnableMenuItem ( hFileMenu, IDM_UNSHARE, MF_BYCOMMAND | MF_GRAYED);
  573. EnableMenuItem ( hFileMenu, IDM_PROPERTIES, MF_BYCOMMAND | MF_GRAYED);
  574. }
  575. // get rid of connect/disonnect entries?
  576. if ( !fNetDDEActive )
  577. {
  578. EnableMenuItem ( hFileMenu, IDM_CONNECT, MF_BYCOMMAND | MF_GRAYED);
  579. EnableMenuItem ( hFileMenu, IDM_DISCONNECT, MF_BYCOMMAND | MF_GRAYED);
  580. }
  581. DrawMenuBar(hwndApp);
  582. if ( ReadWindowPlacement ( szAppName, &Wpl ))
  583. {
  584. Wpl.showCmd = nCmdShow;
  585. Wpl.ptMaxPosition.x = -1;
  586. Wpl.ptMaxPosition.y = -1;
  587. SetWindowPlacement ( hwndApp, &Wpl );
  588. UpdateWindow(hwndApp);
  589. }
  590. else
  591. {
  592. ShowWindow ( hwndApp, nCmdShow );
  593. }
  594. // make our SetCapture target window
  595. if ( !( hwndDummy = CreateWindow (szDummy,
  596. szNull,
  597. WS_CHILD & ~WS_VISIBLE,
  598. 0,
  599. 0,
  600. 0,
  601. 0,
  602. hwndApp,
  603. NULL,
  604. hInstance,
  605. NULL )))
  606. return FALSE;
  607. // Make clipboard window -- needs to happen BEFORE we SetClipboardViewer,
  608. // because hwndApp will get a WM_DRAWCLIPBOARD and there won't be any windows.
  609. SendMessage ( hwndApp, WM_COMMAND, IDM_CLPWND, 0L );
  610. // Attach us to the clipboard viewer chain
  611. hwndNextViewer = SetClipboardViewer(hwndApp);
  612. // create initial local window.
  613. SendMessage ( hwndApp, WM_COMMAND, IDM_LOCAL, 0L );
  614. // force paint before restoring other connections so we don't
  615. // have to wait too long.
  616. UpdateWindow(hwndApp);
  617. // restore previous connections
  618. if ( fNetDDEActive )
  619. RestoreAllSavedConnections();
  620. return TRUE;
  621. }
  622. // Strip all chars between lower and upper from string s, in place.
  623. VOID StripCharRange (
  624. TCHAR *s,
  625. char lower,
  626. char upper)
  627. {
  628. TCHAR *p = s, *q = s;
  629. while( *p ){
  630. if (IsDBCSLeadByte(*p)) {
  631. *q++ = *p++;
  632. *q++ = *p++;
  633. }
  634. else {
  635. if (*p < lower || *p > upper) *q++ = *p++;
  636. else
  637. p++;
  638. }
  639. }
  640. *q = TEXT('\0');
  641. }
  642. // Strip all occurrences of "(&)" from string s, in place
  643. // Localized FE build uses "Bitmap(&B)" instead of "&Bitmap" in menu string.
  644. VOID StripAcceleratorKey (
  645. TCHAR *s)
  646. {
  647. TCHAR *p = s, *q = s;
  648. while( *p ) {
  649. #ifndef UNICODE
  650. if (IsDBCSLeadByte(*p)) {
  651. *q++ = *p++;
  652. *q++ = *p++;
  653. }
  654. else
  655. {
  656. if ( (*p==TEXT('(')) && (*(p+1)==TEXT('&')) && (*(p+3)==TEXT(')')) )
  657. p += 4;
  658. else *q++ = *p++;
  659. }
  660. #else
  661. if ( (*p==TEXT('(')) && (*(p+1)==TEXT('&')) && (*(p+3)==TEXT(')')) )
  662. p += 4;
  663. else *q++ = *p++;
  664. #endif
  665. }
  666. *q = TEXT('\0');
  667. }
  668. /////////////////////////////////////////////////////////////////////////////
  669. //
  670. // Purpose: Message handler for WM_DRAWCLIPBOARD
  671. //
  672. // Params:
  673. // hwnd - Window handle
  674. /////////////////////////////////////////////////////////////////////////////
  675. void OnDrawClipboard(
  676. HWND hwnd)
  677. {
  678. UINT wNewFormat;
  679. UINT wOldFormat;
  680. HCURSOR hCursor;
  681. // If we are in a transaction, defer processing this message
  682. // until the next unlock - if we did this now we could cause
  683. // other apps to break...
  684. // clipboard may have been empty and now isn't
  685. InitializeMenu ( GetMenu(hwnd) );
  686. if (fAppLockedState)
  687. {
  688. fClipboardNeedsPainting = TRUE;
  689. }
  690. else
  691. {
  692. fClipboardNeedsPainting = FALSE;
  693. hCursor = SetCursor (LoadCursor (NULL, IDC_WAIT));
  694. if (IsWindow ( hwndClpbrd ))
  695. {
  696. wOldFormat = GetBestFormat (hwndClpbrd,
  697. GETMDIINFO(hwndClpbrd)->CurSelFormat );
  698. GETMDIINFO(hwndClpbrd)->CurSelFormat = CBM_AUTO;
  699. GETMDIINFO(hwndClpbrd)->fDisplayFormatChanged = TRUE;
  700. wNewFormat = GetBestFormat( hwndClpbrd, CBM_AUTO );
  701. // NOTE OwnerDisplay stuff applies only to the "real" clipboard!
  702. ShowHideControls(hwndClpbrd);
  703. if (wOldFormat == CF_OWNERDISPLAY)
  704. {
  705. /* Save the owner Display Scroll info */
  706. SaveOwnerScrollInfo(hwndClpbrd);
  707. ShowScrollBar ( hwndClpbrd, SB_BOTH, FALSE );
  708. ResetScrollInfo( hwndClpbrd );
  709. InvalidateRect ( hwndClpbrd, NULL, TRUE );
  710. }
  711. else
  712. {
  713. if (wNewFormat == CF_OWNERDISPLAY)
  714. {
  715. /* Restore the owner display scroll info */
  716. ShowHideControls(hwndClpbrd);
  717. ShowWindow ( pActiveMDI->hwndSizeBox, SW_HIDE );
  718. RestoreOwnerScrollInfo(hwndClpbrd);
  719. InvalidateRect ( hwndClpbrd, NULL, TRUE );
  720. }
  721. else
  722. {
  723. // Change the character dimensions based on the format.
  724. ChangeCharDimensions(hwndClpbrd, wOldFormat, wNewFormat);
  725. // Initialize the owner display scroll info, because the
  726. // contents have changed.
  727. InitOwnerScrollInfo();
  728. // Force a total repaint. fOwnerDisplay gets updated during
  729. // a total repaint.
  730. InvalidateRect(hwndClpbrd, NULL, TRUE);
  731. ResetScrollInfo(hwndClpbrd);
  732. // force update here BEFORE sending on WM_DRAWCLIPBOARD
  733. UpdateWindow (hwndClpbrd);
  734. }
  735. }
  736. }
  737. SetCursor (hCursor);
  738. }
  739. // Pass the message on to the next clipboard viewer in the chain.
  740. if (hwndNextViewer != NULL)
  741. {
  742. SendMessage(hwndNextViewer, WM_DRAWCLIPBOARD, 0, 0);
  743. }
  744. }
  745. LRESULT OnEraseBkgnd(
  746. HWND hwnd,
  747. HDC hdc)
  748. {
  749. return DefMDIChildProc(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0L);
  750. }
  751. LRESULT OnPaint(
  752. HWND hwnd)
  753. {
  754. PMDIINFO pMDI;
  755. PAINTSTRUCT ps;
  756. HPALETTE hpal;
  757. HPALETTE hpalT;
  758. HBRUSH hbr;
  759. LRESULT lRet = ONPAINT_FAIL;
  760. HCURSOR hCursor;
  761. if (!(pMDI = GETMDIINFO(hwnd)))
  762. {
  763. return ONPAINT_FAIL;
  764. }
  765. hCursor = SetCursor (LoadCursor (NULL, IDC_WAIT));
  766. if ( IsIconic ( hwnd ))
  767. {
  768. BeginPaint(hwnd, &ps);
  769. if ( pMDI->flags & F_CLPBRD )
  770. {
  771. DrawIcon ( ps.hdc, 0, 0, hicClipbrd);
  772. }
  773. else if ( pMDI->flags & F_LOCAL )
  774. {
  775. DrawIcon ( ps.hdc, 0, 0, hicClipbook);
  776. }
  777. else
  778. {
  779. DrawIcon ( ps.hdc, 0, 0, hicRemote);
  780. }
  781. lRet = ONPAINT_SUCCESS;
  782. goto donePaint;
  783. }
  784. if (pMDI->DisplayMode != DSP_PAGE)
  785. {
  786. BeginPaint (hwnd, &ps);
  787. lRet = ONPAINT_FAIL;
  788. goto donePaint;
  789. }
  790. if (fAppShuttingDown)
  791. {
  792. BeginPaint (hwnd, &ps);
  793. lRet = ONPAINT_FAIL;
  794. goto donePaint;
  795. }
  796. if (!VOpenClipboard( pMDI->pVClpbrd, hwnd))
  797. {
  798. #if DEBUG
  799. SetStatusBarText("Clipboard changed but could not open");
  800. #endif
  801. lRet = ONPAINT_NOCLIPBRD;
  802. goto done;
  803. }
  804. BeginPaint (hwnd, &ps);
  805. // Fill background with proper color - DefMDIChildProc fills with app_workspace.
  806. hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  807. FillRect(ps.hdc, &ps.rcPaint, hbr);
  808. DeleteObject(hbr);
  809. SetBkColor(ps.hdc, GetSysColor(COLOR_WINDOW));
  810. SetTextColor(ps.hdc, GetSysColor(COLOR_WINDOWTEXT));
  811. if (hpal = VGetClipboardData( pMDI->pVClpbrd, CF_PALETTE))
  812. {
  813. PINFO("Palette found, selecting & realizing\r\n");
  814. hpalT = SelectPalette(ps.hdc, hpal, pMDI != pActiveMDI );
  815. RealizePalette(ps.hdc);
  816. }
  817. DrawStuff( hwnd, &ps, hwnd );
  818. if (hpal)
  819. {
  820. // We don't want to put the DEFAULT palette in the foreground.
  821. SelectPalette(ps.hdc, hpalT, FALSE);
  822. }
  823. VCloseClipboard( pMDI->pVClpbrd );
  824. lRet = ONPAINT_SUCCESS;
  825. donePaint:
  826. EndPaint(hwnd, &ps);
  827. done:
  828. SetCursor (hCursor);
  829. return lRet;
  830. }
  831. LRESULT CALLBACK FrameWndProc(
  832. HWND hwnd,
  833. UINT msg,
  834. WPARAM wParam,
  835. LPARAM lParam)
  836. {
  837. int tmp;
  838. // PINFO(TEXT("FrameWnd Msg: %u %ld %ld\r\n"), msg, wParam, lParam);
  839. switch (msg)
  840. {
  841. case WM_CREATE:
  842. {
  843. CLIENTCREATESTRUCT ccs;
  844. RECT rc;
  845. /* Find window menu where children will be listed */
  846. ccs.hWindowMenu = GetSubMenu (GetMenu(hwnd), WINDOW_MENU_INDEX );
  847. ccs.idFirstChild = 4100; // IDM_WINDOWCHILD;
  848. // initialize special case clipboard formats...
  849. // note that CF_BITMAP, CF_METAFILEPICT, CF_PALETTE are
  850. // re-registered in a private format because data for these
  851. // formats is exchanged between this app and clipsrv.exe in
  852. // a flat DDEML data handle - not the regular DDE interpretation
  853. // of a handle that carries those format IDs
  854. if (LoadString (hInst, CF_BITMAP, szBuf, SZBUFSIZ))
  855. cf_bitmap = RegisterClipboardFormat (szBuf);
  856. if (LoadString (hInst, CF_METAFILEPICT, szBuf, SZBUFSIZ))
  857. cf_metafilepict = RegisterClipboardFormat (szBuf);
  858. if (LoadString (hInst, CF_PALETTE, szBuf, SZBUFSIZ))
  859. cf_palette = RegisterClipboardFormat (szBuf);
  860. cf_preview = RegisterClipboardFormat (SZPREVNAME);
  861. cf_link = RegisterClipboardFormat (SZLINK);
  862. cf_linkcopy = RegisterClipboardFormat (SZLINKCOPY);
  863. cf_objectlink = RegisterClipboardFormat (SZOBJECTLINK);
  864. cf_objectlinkcopy = RegisterClipboardFormat (SZOBJECTLINKCOPY);
  865. CreateTools( hwnd ); // creates toolbar window, brushes, etc.
  866. // determine height of toolbar window and save...
  867. GetClientRect ( hwndToolbar, &rc );
  868. dyButtonBar = rc.bottom - rc.top +1;
  869. // determine height of statusbar window and save...
  870. GetClientRect ( hwndStatus, &rc );
  871. dyStatus = rc.bottom - rc.top;
  872. // Create the MDI client - will be sized later
  873. hwndMDIClient = CreateWindow ("mdiclient",
  874. NULL,
  875. WS_BORDER|
  876. WS_CHILD|
  877. WS_CLIPCHILDREN|
  878. MDIS_ALLCHILDSTYLES|
  879. WS_HSCROLL|
  880. WS_VSCROLL,
  881. 0,
  882. 0,
  883. 0,
  884. 0,
  885. hwnd,
  886. (HMENU)0xCAC,
  887. hInst,
  888. (LPVOID)&ccs);
  889. ShowWindow ( hwndMDIClient, SW_SHOW );
  890. }
  891. break;
  892. case WM_QUERYNEWPALETTE:
  893. // Tell the active document to realize in foreground.
  894. if ( hwndActiveChild )
  895. tmp = (WORD)SendMessage(hwndActiveChild, WM_QUERYNEWPALETTE,0, 0L);
  896. else
  897. break;
  898. // If mapping is unchanged, other documents could still change,
  899. // so give them a change to realize.
  900. if (!tmp)
  901. SendMessageToKids(WM_PALETTECHANGED, (WPARAM)hwndActiveChild, 0L);
  902. return(tmp);
  903. break;
  904. // System palette has changed, so pass it on to the children.
  905. case WM_PALETTECHANGED:
  906. SendMessageToKids(WM_PALETTECHANGED, wParam, lParam);
  907. break;
  908. case WM_MENUSELECT:
  909. PINFO(TEXT("MenuSelect %lx\r\n"), wParam);
  910. // no context menu help for popup entries
  911. if ( HIWORD(wParam) & MF_POPUP )
  912. {
  913. dwCurrentHelpId = 0;
  914. }
  915. else if ( HIWORD(wParam) & MF_SYSMENU )
  916. {
  917. dwCurrentHelpId = IDH_SYSMENU;
  918. }
  919. else
  920. {
  921. // We don't care if the menuitem's disabled, checked, whatever...
  922. wParam = LOWORD(wParam);
  923. // was this a dynamically added clipboard entry?
  924. if (( wParam >= 0xc000 && wParam <= 0xffff || // registerd format?
  925. wParam >= CF_TEXT && wParam <= CF_ENHMETAFILE || // intrinsic format?
  926. wParam >= CF_OWNERDISPLAY && wParam <= CF_DSPMETAFILEPICT )
  927. // gotta exclude sc_ stuff - overlaps with formats
  928. && ! ( wParam >= SC_SIZE && wParam <= SC_HOTKEY ) )
  929. {
  930. GetMenuString ( GetMenu(hwnd), (UINT)wParam,
  931. szBuf2, SZBUFSIZ, MF_BYCOMMAND );
  932. //Localized FE build uses "Bitmap(&B)" instead of "&Bitmap" in menu string.
  933. StripAcceleratorKey( szBuf2 );
  934. //For non-localized string
  935. StripCharRange ( szBuf2, '&', '&' );
  936. StringCchPrintf( szBuf, sizeof(szBuf), szViewHelpFmt, (LPSTR)szBuf2 );
  937. SendMessage( hwndStatus, SB_SETTEXT, SBT_NOBORDERS|255, (LPARAM)szBuf );
  938. dwCurrentHelpId = (DWORD)(IDH_FORMATS_BASE + wParam);
  939. break;
  940. }
  941. if ( wParam >= 4100 && wParam <= 4200 )
  942. {
  943. GetMenuString (GetMenu(hwnd), (UINT)wParam,szBuf2,SZBUFSIZ, MF_BYCOMMAND);
  944. StripCharRange ( szBuf2, '&', '&' );
  945. StripCharRange ( szBuf2, '0', '9' );
  946. StringCchPrintf( szBuf, sizeof(szBuf), szActivateFmt,
  947. *szBuf2 == ' ' ? (LPSTR)(szBuf2+1) : (LPSTR)szBuf2 );
  948. SendMessage( hwndStatus, SB_SETTEXT, SBT_NOBORDERS|255, (LPARAM)(LPSTR)szBuf );
  949. dwCurrentHelpId = IDH_NAMESWIND;
  950. break;
  951. }
  952. dwCurrentHelpId = (DWORD)(IDH_BASE + wParam);
  953. }
  954. MenuHelp( (WORD)msg, wParam, lParam, GetMenu(hwnd), hInst, hwndStatus, nIDs );
  955. break;
  956. case WM_F1DOWN:
  957. PINFO(TEXT("Help on context %ld\r\n"), dwCurrentHelpId);
  958. if ( dwCurrentHelpId )
  959. {
  960. WinHelp(hwndApp, szHelpFile, HELP_CONTEXT, dwCurrentHelpId );
  961. DrawMenuBar(hwndApp);
  962. }
  963. break;
  964. case WM_DRAWITEM:
  965. HandleOwnerDraw( hwnd, msg, wParam, lParam );
  966. break;
  967. case WM_INITMENU:
  968. InitializeMenu ((HMENU)wParam);
  969. UpdateCBMenu ( hwnd, hwndActiveChild );
  970. break;
  971. case WM_SYSCOLORCHANGE:
  972. DeleteTools( hwnd );
  973. CreateTools( hwnd );
  974. break;
  975. case WM_COMMAND:
  976. return ClipBookCommand ( hwnd, msg, wParam, lParam );
  977. case WM_CLOSE:
  978. #if DEBUG
  979. if ( fAppLockedState )
  980. PERROR(TEXT("Very bad: WM_CLOSE while locked\n\r"));
  981. #endif
  982. // force all clipboard formats rendered before exiting
  983. // so we don't end up yielding in WM_RENDERALLFORMATS
  984. // and get into trouble.
  985. fAppShuttingDown = TRUE;
  986. ForceRenderAll(hwnd, (PVCLPBRD)NULL );
  987. PostMessage(hwnd, WM_CLOSE_REALLY, 0, 0L );
  988. WinHelp(hwnd, szHelpFile, HELP_QUIT, 0L);
  989. break;
  990. case WM_NOTIFY:
  991. {
  992. LPTOOLTIPTEXT lpTTT = (LPTOOLTIPTEXT) lParam;
  993. if (lpTTT->hdr.code == TTN_NEEDTEXT)
  994. {
  995. LoadString (hInst, (UINT)(MH_TOOLTIP + lpTTT->hdr.idFrom), lpTTT->szText, 80);
  996. return TRUE;
  997. }
  998. }
  999. break;
  1000. case WM_CLOSE_REALLY:
  1001. // this is necessary to avoid processing messages in our
  1002. // queue when we yield getting the clipboard data in
  1003. // ForceRenderAll and destroying the app prematurely
  1004. return DefFrameProc (hwnd,hwndMDIClient,WM_CLOSE,0,0L);
  1005. case WM_DESTROY:
  1006. #if DEBUG
  1007. if ( fAppLockedState )
  1008. {
  1009. PERROR(TEXT("Very bad: WM_DESTROY while locked\n\r"));
  1010. }
  1011. #endif
  1012. // Take us out of the viewer chain
  1013. ChangeClipboardChain(hwnd, hwndNextViewer);
  1014. DeleteTools ( hwnd );
  1015. Wpl.length = sizeof ( Wpl );
  1016. Wpl.flags = 0;
  1017. GetWindowPlacement ( hwnd, &Wpl );
  1018. SaveWindowPlacement ( &Wpl );
  1019. if (hkeyRoot != NULL)
  1020. {
  1021. RegSetValueEx (hkeyRoot, szStatusbar, 0L, REG_DWORD,
  1022. (LPBYTE)&fStatus, sizeof(fStatus));
  1023. RegSetValueEx (hkeyRoot, szToolbar, 0L, REG_DWORD,
  1024. (LPBYTE)&fToolBar, sizeof(fToolBar));
  1025. RegSetValueEx (hkeyRoot, szShPref, 0L, REG_DWORD,
  1026. (LPBYTE)&fSharePreference, sizeof(fSharePreference));
  1027. }
  1028. PostQuitMessage (0);
  1029. break;
  1030. case WM_DRAWCLIPBOARD:
  1031. OnDrawClipboard(hwnd);
  1032. break;
  1033. case WM_CHANGECBCHAIN:
  1034. if (hwndNextViewer == NULL)
  1035. return(FALSE);
  1036. if ( (HWND)wParam == hwndNextViewer)
  1037. {
  1038. hwndNextViewer = (HWND)lParam;
  1039. return(TRUE);
  1040. }
  1041. return(SendMessage(hwndNextViewer, WM_CHANGECBCHAIN, wParam, lParam));
  1042. case WM_RENDERALLFORMATS:
  1043. // WM_DESTROY follows close on the heels of this message, and
  1044. // we will process it and die while another copy of FrameWndProc
  1045. // is in sync DDEML transaction...
  1046. //
  1047. // Note that we now attempt to render all formats in WM_DESTROY
  1048. // before doing the PostQuitMessage so we should not have to
  1049. // respond to this message.
  1050. break;
  1051. case WM_RENDERFORMAT:
  1052. {
  1053. HDDEDATA hListData = 0L;
  1054. HDDEDATA hFmtData = 0L;
  1055. HSZ hszFmt = 0L;
  1056. LPTSTR lpszList = TEXT("");
  1057. LPTSTR q;
  1058. DWORD cbDataLen;
  1059. UINT RealFmt;
  1060. UINT uiErr;
  1061. PINFO(TEXT("Frame WM_RENDERFORMAT: %d\r\n"),wParam);
  1062. // If we did File/Save or File/Open then render from file.
  1063. // When we get IDM_COPY, szSaveFileName will assigned ""
  1064. if (szSaveFileName[0])
  1065. {
  1066. SetClipboardData((UINT)wParam, RenderFormatFromFile(szSaveFileName,
  1067. (WORD)wParam));
  1068. break;
  1069. }
  1070. if ( !IsWindow(hwndClpOwner))
  1071. {
  1072. PERROR(TEXT("Strange?: null clipboard owner window!\n\r"));
  1073. break;
  1074. }
  1075. DdeKeepStringHandle ( idInst, hszFormatList );
  1076. hListData = MySyncXact (NULL,
  1077. 0L,
  1078. GETMDIINFO(hwndClpOwner)->hClpConv,
  1079. hszFormatList,
  1080. CF_TEXT,
  1081. XTYP_REQUEST,
  1082. SHORT_SYNC_TIMEOUT,
  1083. NULL);
  1084. if (!hListData && !fAppShuttingDown)
  1085. {
  1086. uiErr = DdeGetLastError (idInst);
  1087. PERROR (TEXT("WM_RENDERFORM: REQUEST for formatlist failed: %x\n\r"),uiErr);
  1088. MessageBoxID (hInst,
  1089. hwnd,
  1090. IDS_DATAUNAVAIL,
  1091. IDS_APPNAME,
  1092. MB_OK|MB_ICONEXCLAMATION);
  1093. break;
  1094. }
  1095. lpszList = (LPTSTR)DdeAccessData ( hListData, &cbDataLen );
  1096. if (!lpszList && !fAppShuttingDown)
  1097. {
  1098. PERROR(TEXT("WM_RENDERFORM: DdeAccessData failed!\n\r"));
  1099. MessageBoxID (hInst,
  1100. hwnd,
  1101. IDS_DATAUNAVAIL,
  1102. IDS_APPNAME,
  1103. MB_OK|MB_ICONEXCLAMATION);
  1104. break;
  1105. }
  1106. for (q = strtokA (lpszList, "\t"); q; q = strtokA(NULL, "\t"))
  1107. {
  1108. RealFmt = MyGetFormat ( q, GETFORMAT_DONTLIE );
  1109. if ( wParam == RealFmt || msg == WM_RENDERALLFORMATS )
  1110. {
  1111. PINFO(TEXT("Getting format %d\r\n"), RealFmt);
  1112. hszFmt = DdeCreateStringHandle ( idInst, q, 0 );
  1113. hFmtData = MySyncXact (NULL,
  1114. 0L,
  1115. GETMDIINFO(hwndClpOwner)->hClpConv,
  1116. hszFmt,
  1117. MyGetFormat (q, GETFORMAT_LIE),
  1118. XTYP_REQUEST,
  1119. LONG_SYNC_TIMEOUT,
  1120. NULL );
  1121. if (hFmtData)
  1122. {
  1123. SetClipboardFormatFromDDE ( hwndClpbrd, RealFmt , hFmtData );
  1124. }
  1125. else
  1126. PERROR(TEXT("REQUEST for %s failed %x\n\r"), q, DdeGetLastError(idInst));
  1127. DdeFreeStringHandle (idInst, hszFmt);
  1128. }
  1129. }
  1130. DdeUnaccessData( hListData );
  1131. DdeFreeDataHandle ( hListData );
  1132. // Couldn't find Bitmap, try DIB and
  1133. // and convert it to Bitmap.
  1134. if (wParam == CF_BITMAP && !hFmtData)
  1135. {
  1136. TCHAR szName[40];
  1137. GetClipboardName (CF_DIB, szName, sizeof (szName));
  1138. hszFmt = DdeCreateStringHandle (idInst, szName, 0);
  1139. hFmtData = MySyncXact (NULL,
  1140. 0L,
  1141. GETMDIINFO (hwndClpOwner)->hClpConv,
  1142. hszFmt,
  1143. MyGetFormat (szName, GETFORMAT_LIE),
  1144. XTYP_REQUEST,
  1145. LONG_SYNC_TIMEOUT,
  1146. NULL);
  1147. if (hFmtData)
  1148. SetClipboardFormatFromDDE (hwndClpbrd, DDE_DIB2BITMAP, hFmtData);
  1149. DdeFreeStringHandle (idInst, hszFmt);
  1150. }
  1151. break;
  1152. }
  1153. case WM_SIZE:
  1154. SendMessage (hwndToolbar, WM_SIZE, 0, 0L);
  1155. SendMessage (hwndStatus, WM_SIZE, 0, 0L);
  1156. AdjustMDIClientSize();
  1157. break;
  1158. case WM_PARENTNOTIFY:
  1159. // PINFO(TEXT("Recieved WM_PARENTNOTIFY %d %ld\r\n"), wParam, lParam);
  1160. break;
  1161. default:
  1162. return DefFrameProc (hwnd,hwndMDIClient,msg,wParam,lParam);
  1163. }
  1164. return 0;
  1165. }
  1166. //////////////////////////////////////////////////////////////////////
  1167. LRESULT CALLBACK ChildWndProc(
  1168. HWND hwnd,
  1169. UINT msg,
  1170. WPARAM wParam,
  1171. LPARAM lParam)
  1172. {
  1173. LPMEASUREITEMSTRUCT lpmisCtl;
  1174. HDC hdc;
  1175. int tmp;
  1176. PMDIINFO pMDI;
  1177. int i;
  1178. HPALETTE hCurrentPal, hOldPal;
  1179. // PERROR(TEXT("ChildWndProc msg: %u %ld %ld\r\n"),msg, wParam, lParam);
  1180. switch (msg)
  1181. {
  1182. case WM_MDIACTIVATE:
  1183. SendMessage(hwndMDIClient, WM_MDIREFRESHMENU, 0, 0);
  1184. DrawMenuBar(hwndApp);
  1185. if ((HWND)lParam != hwnd)
  1186. break;
  1187. // intentional fall through
  1188. case WM_SETFOCUS:
  1189. hwndActiveChild = hwnd;
  1190. if (!(pActiveMDI = GETMDIINFO(hwndActiveChild)))
  1191. break;
  1192. if ( pActiveMDI->DisplayMode != DSP_PAGE &&
  1193. IsWindow( pActiveMDI->hWndListbox ))
  1194. {
  1195. SetFocus ( pActiveMDI->hWndListbox );
  1196. }
  1197. else
  1198. {
  1199. SetFocus ( hwndActiveChild );
  1200. }
  1201. InitializeMenu( GetMenu(hwndApp) );
  1202. UpdateNofMStatus(hwndActiveChild);
  1203. return (DefMDIChildProc(hwnd, msg, wParam, lParam));
  1204. case WM_LBUTTONDBLCLK:
  1205. if (!GETMDIINFO(hwnd))
  1206. break;
  1207. if (GETMDIINFO (hwnd)->DisplayMode == DSP_PAGE &&
  1208. !(GETMDIINFO(hwnd)->flags & F_CLPBRD ))
  1209. {
  1210. if (GETMDIINFO(hwnd)->OldDisplayMode == DSP_LIST )
  1211. SendMessage ( hwndApp, WM_COMMAND, IDM_LISTVIEW, 0L );
  1212. else if ( GETMDIINFO(hwnd)->OldDisplayMode == DSP_PREV )
  1213. SendMessage ( hwndApp, WM_COMMAND, IDM_PREVIEWS, 0L );
  1214. }
  1215. break;
  1216. case WM_PALETTECHANGED:
  1217. if (hwnd == (HWND)wParam)
  1218. break;
  1219. // intentional fall through
  1220. case WM_QUERYNEWPALETTE:
  1221. if (!GETMDIINFO(hwnd))
  1222. break;
  1223. if (GETMDIINFO(hwnd)->DisplayMode != DSP_PAGE)
  1224. return 0;
  1225. i = 0;
  1226. if (VOpenClipboard( GETMDIINFO(hwnd)->pVClpbrd, hwnd))
  1227. {
  1228. if ( hCurrentPal = VGetClipboardData( GETMDIINFO(hwnd)->pVClpbrd, CF_PALETTE))
  1229. {
  1230. hdc = GetDC(hwnd);
  1231. hOldPal = SelectPalette (hdc,
  1232. hCurrentPal,
  1233. (msg == WM_QUERYNEWPALETTE)? FALSE: TRUE);
  1234. i = RealizePalette(hdc);
  1235. SelectPalette(hdc, hOldPal, TRUE);
  1236. RealizePalette(hdc);
  1237. ReleaseDC(hwnd, hdc);
  1238. if (i)
  1239. InvalidateRect(hwnd, NULL, TRUE);
  1240. }
  1241. VCloseClipboard( GETMDIINFO(hwnd)->pVClpbrd );
  1242. }
  1243. return(i);
  1244. break;
  1245. case WM_MENUSELECT:
  1246. MenuHelp ((WORD)msg,
  1247. wParam,
  1248. lParam,
  1249. GetMenu(hwndApp),
  1250. hInst,
  1251. hwndStatus,
  1252. nIDs);
  1253. break;
  1254. case WM_CREATE:
  1255. if ((pMDI = (LPMDIINFO)GlobalAllocPtr(GPTR, sizeof(MDIINFO))) == NULL)
  1256. {
  1257. PERROR(TEXT("MdiInfo alloc failed\n\r"));
  1258. break;
  1259. }
  1260. SetWindowLongPtr (hwnd, GWL_MDIINFO, (LONG_PTR)pMDI);
  1261. pMDI->DisplayMode = DSP_LIST;
  1262. pMDI->hExeConv = 0L;
  1263. pMDI->hClpConv = 0L;
  1264. pMDI->hVClpConv = 0L;
  1265. pMDI->flags = 0L;
  1266. pMDI->CurSelFormat = CBM_AUTO;
  1267. pMDI->cyScrollLast = -1L;
  1268. pMDI->cxScrollLast = -1;
  1269. pMDI->cyScrollNow = 0L;
  1270. pMDI->cxScrollNow = 0;
  1271. pMDI->pVClpbrd = NULL;
  1272. pMDI->hszConvPartner = 0L;
  1273. pMDI->hszConvPartnerNP = 0L;
  1274. pMDI->hszClpTopic = 0L;
  1275. pMDI->fDisplayFormatChanged = TRUE;
  1276. pMDI->hWndListbox = CreateWindow (TEXT("listbox"),
  1277. szNull,
  1278. WS_CHILD |
  1279. LBS_STANDARD |
  1280. LBS_NOINTEGRALHEIGHT |
  1281. LBS_LISTVIEW,
  1282. 0,
  1283. 0,
  1284. 100,
  1285. 100,
  1286. hwnd,
  1287. (HMENU)ID_LISTBOX,
  1288. hInst,
  1289. 0L );
  1290. // create the scroll bars
  1291. pMDI->hwndVscroll = CreateWindowW (L"scrollbar",
  1292. L"",
  1293. WS_CHILD|SBS_VERT,
  1294. 0,
  1295. 0,
  1296. 0,
  1297. 0,
  1298. hwnd,
  1299. (HMENU)ID_VSCROLL,
  1300. hInst,
  1301. 0L);
  1302. pMDI->hwndHscroll = CreateWindowW (L"scrollbar",
  1303. L"",
  1304. WS_CHILD|SBS_HORZ,
  1305. 0,
  1306. 0,
  1307. 0,
  1308. 0,
  1309. hwnd,
  1310. (HMENU)ID_VSCROLL,
  1311. hInst,
  1312. 0L);
  1313. // create the corner size box
  1314. pMDI->hwndSizeBox = CreateWindowW (L"scrollbar",
  1315. L"",
  1316. WS_CHILD|SBS_SIZEBOX,
  1317. 0,
  1318. 0,
  1319. 0,
  1320. 0,
  1321. hwnd,
  1322. (HMENU)ID_SIZEBOX,
  1323. hInst,
  1324. 0L);
  1325. // create the page fwd/bkwd buttons
  1326. pMDI->hwndPgUp = CreateWindowW (L"button",
  1327. L"",
  1328. WS_CHILD | BS_OWNERDRAW,
  1329. 0,
  1330. 0,
  1331. 0,
  1332. 0,
  1333. hwnd,
  1334. (HMENU)ID_PAGEUP,
  1335. hInst,
  1336. 0L);
  1337. pMDI->hwndPgDown = CreateWindowW (L"button",
  1338. L"",
  1339. WS_CHILD | BS_OWNERDRAW,
  1340. 0,
  1341. 0,
  1342. 0,
  1343. 0,
  1344. hwnd,
  1345. (HMENU)ID_PAGEDOWN,
  1346. hInst,
  1347. 0L);
  1348. SetCharDimensions( hwnd, GetStockObject (SYSTEM_FONT));
  1349. break;
  1350. case WM_VSCROLL:
  1351. if (wParam != SB_THUMBTRACK)
  1352. {
  1353. if (fOwnerDisplay)
  1354. SendOwnerMessage (WM_VSCROLLCLIPBOARD, (WPARAM)hwnd, (LPARAM)wParam);
  1355. else
  1356. ClipbrdVScroll (hwnd, LOWORD(wParam), HIWORD(wParam));
  1357. }
  1358. break;
  1359. case WM_HSCROLL:
  1360. if (wParam != SB_THUMBTRACK)
  1361. {
  1362. if (fOwnerDisplay)
  1363. SendOwnerMessage (WM_HSCROLLCLIPBOARD, (WPARAM)hwnd, (LPARAM)wParam);
  1364. else
  1365. ClipbrdHScroll (hwnd, LOWORD(wParam), HIWORD(wParam));
  1366. }
  1367. break;
  1368. case WM_QUERYDRAGICON:
  1369. if (!GETMDIINFO(hwnd))
  1370. break;
  1371. if (GETMDIINFO(hwnd)->flags & F_CLPBRD)
  1372. return (LRESULT)hcurClipbrd;
  1373. else if ( GETMDIINFO(hwnd)->flags & F_LOCAL )
  1374. return (LRESULT)hcurClipbook;
  1375. else
  1376. return (LRESULT)hcurRemote;
  1377. case WM_CLOSE:
  1378. if (!GETMDIINFO(hwnd))
  1379. {
  1380. if (!(GETMDIINFO(hwnd)->flags & (F_CLPBRD | F_LOCAL)))
  1381. {
  1382. PINFO(TEXT("removing reconn for '%s'\n\r"), (LPSTR)GETMDIINFO(hwnd)->szBaseName);
  1383. if (NULL != hkeyRoot)
  1384. {
  1385. StringCchCopy(szBuf, SZBUFSIZ, GETMDIINFO(hwnd)->szBaseName);
  1386. StringCchCat( szBuf, SZBUFSIZ, szConn);
  1387. RegDeleteValue(hkeyRoot, szBuf);
  1388. StringCchCopy(szBuf, SZBUFSIZ, GETMDIINFO(hwnd)->szBaseName);
  1389. StringCchCat (szBuf, SZBUFSIZ, szWindows);
  1390. RegDeleteValue(hkeyRoot, szBuf);
  1391. }
  1392. }
  1393. }
  1394. WinHelp(hwnd, szHelpFile, HELP_QUIT, 0L);
  1395. return(DefMDIChildProc(hwnd, msg, wParam, lParam));
  1396. case WM_PAINT:
  1397. switch (OnPaint(hwnd))
  1398. {
  1399. case ONPAINT_SUCCESS: return TRUE;
  1400. case ONPAINT_FAIL: return FALSE;
  1401. case ONPAINT_NOCLIPBRD: PostMessage (hwnd, msg, wParam, lParam);
  1402. default: return FALSE;
  1403. }
  1404. break;
  1405. case WM_KEYDOWN:
  1406. {
  1407. WORD sb;
  1408. if (!(pMDI = GETMDIINFO(hwnd)))
  1409. break;
  1410. if ( pMDI->DisplayMode != DSP_PAGE )
  1411. return (DefMDIChildProc(hwnd, msg, wParam, lParam));
  1412. switch (wParam)
  1413. {
  1414. case VK_UP:
  1415. sb = SB_LINEUP;
  1416. goto VertScroll;
  1417. case VK_DOWN:
  1418. sb = SB_LINEDOWN;
  1419. goto VertScroll;
  1420. case VK_PRIOR:
  1421. sb = SB_PAGEUP;
  1422. goto VertScroll;
  1423. case VK_NEXT:
  1424. sb = SB_PAGEDOWN;
  1425. VertScroll:
  1426. SendMessage(hwnd, WM_VSCROLL, sb, 0L);
  1427. break;
  1428. case VK_LEFT:
  1429. sb = SB_LINEUP;
  1430. goto HorzScroll;
  1431. case VK_RIGHT:
  1432. sb = SB_LINEDOWN;
  1433. goto HorzScroll;
  1434. case VK_TAB:
  1435. sb = (GetKeyState( VK_SHIFT ) < 0) ? SB_PAGEUP : SB_PAGEDOWN;
  1436. HorzScroll:
  1437. SendMessage( hwnd, WM_HSCROLL, sb, 0L);
  1438. break;
  1439. default:
  1440. return (DefMDIChildProc(hwnd, msg, wParam, lParam));
  1441. }
  1442. }
  1443. break;
  1444. case WM_SIZE:
  1445. if (!(pMDI = GETMDIINFO(hwnd)))
  1446. break;
  1447. AdjustControlSizes( hwnd );
  1448. pMDI->fDisplayFormatChanged = TRUE;
  1449. InvalidateRect (hwnd, NULL, FALSE);
  1450. if ( pMDI->DisplayMode == DSP_PAGE )
  1451. ResetScrollInfo ( hwnd );
  1452. return (DefMDIChildProc(hwnd, msg, wParam, lParam));
  1453. case WM_DRAWITEM:
  1454. HandleOwnerDraw( hwnd, msg, wParam, lParam );
  1455. break;
  1456. case WM_COMPAREITEM:
  1457. if ( wParam != ID_LISTBOX )
  1458. break;
  1459. tmp = lstrcmpi (&((LPLISTENTRY)((LPCOMPAREITEMSTRUCT)lParam)->itemData1)->name[1],
  1460. &((LPLISTENTRY)((LPCOMPAREITEMSTRUCT)lParam)->itemData2)->name[1]);
  1461. if ( tmp < 0 )
  1462. {
  1463. return -1;
  1464. }
  1465. else if (tmp > 0)
  1466. {
  1467. return 1;
  1468. }
  1469. else
  1470. {
  1471. return 0;
  1472. }
  1473. break;
  1474. case WM_DELETEITEM:
  1475. if ( wParam != ID_LISTBOX )
  1476. break;
  1477. // if item is marked for saving (for a new listbox), dont delete
  1478. if ( ((LPLISTENTRY)((LPDELETEITEMSTRUCT)lParam)->itemData)->fDelete == FALSE )
  1479. break;
  1480. // delete preview bmp if there is one
  1481. if (((LPLISTENTRY)((LPDELETEITEMSTRUCT)lParam)->itemData)->hbmp)
  1482. DeleteObject (((LPLISTENTRY)((LPDELETEITEMSTRUCT)lParam)->itemData)->hbmp);
  1483. GlobalFreePtr( (LPVOID)((LPDELETEITEMSTRUCT)lParam)->itemData );
  1484. break;
  1485. case WM_MEASUREITEM:
  1486. lpmisCtl = (MEASUREITEMSTRUCT *) lParam;
  1487. switch ( wParam )
  1488. {
  1489. case ID_LISTBOX:
  1490. if (!GETMDIINFO(hwnd))
  1491. break;
  1492. if (GETMDIINFO(hwnd)->DisplayMode == DSP_LIST)
  1493. lpmisCtl->itemHeight = max( LSTBTDY, dyPrevFont + 1);
  1494. else
  1495. lpmisCtl->itemHeight = 3*dyPrevFont + PREVBMPSIZ + 2*PREVBRD;
  1496. break;
  1497. case ID_PAGEUP:
  1498. case ID_PAGEDOWN:
  1499. lpmisCtl->itemWidth = GetSystemMetrics ( SM_CXHSCROLL );
  1500. lpmisCtl->itemHeight = GetSystemMetrics ( SM_CYVSCROLL );
  1501. break;
  1502. }
  1503. break;
  1504. case WM_COMMAND:
  1505. switch (LOWORD(wParam))
  1506. {
  1507. case ID_LISTBOX:
  1508. if (!GETMDIINFO(hwnd))
  1509. break;
  1510. if (!(IsWindow(GETMDIINFO(hwnd)->hWndListbox)))
  1511. break;
  1512. switch(HIWORD(wParam))
  1513. {
  1514. case LBN_SETFOCUS:
  1515. case LBN_SELCHANGE:
  1516. UpdateNofMStatus(hwnd);
  1517. InitializeMenu( GetMenu(hwndApp));
  1518. break;
  1519. case LBN_SELCANCEL:
  1520. case LBN_KILLFOCUS:
  1521. break;
  1522. case LBN_DBLCLK:
  1523. // Double-clicks cause me to go to page view
  1524. SendMessage (hwndApp, WM_COMMAND, IDM_PAGEVIEW, 0L);
  1525. break;
  1526. }
  1527. break;
  1528. case ID_PAGEUP:
  1529. case ID_PAGEDOWN:
  1530. SendMessage ( hwndApp, WM_COMMAND, wParam, 0L );
  1531. break;
  1532. default:
  1533. return(DefMDIChildProc(hwnd, WM_COMMAND, wParam, lParam));
  1534. }
  1535. break;
  1536. case WM_SYSCOMMAND:
  1537. // The Close menuitem on the system menus of the clipboard and
  1538. // local clipbook windows should be greyed, so we shouldn't get
  1539. // that message.
  1540. switch ( wParam )
  1541. {
  1542. case SC_CLOSE:
  1543. if (!GETMDIINFO(hwnd))
  1544. break;
  1545. // don't allow close of local or clipboard
  1546. if (GETMDIINFO(hwnd)->flags & (F_LOCAL | F_CLPBRD))
  1547. wParam = SC_MINIMIZE;
  1548. break;
  1549. default:
  1550. break;
  1551. }
  1552. return DefMDIChildProc(hwnd, msg, wParam, lParam );
  1553. case WM_DESTROY:
  1554. if (!(pMDI = GETMDIINFO(hwnd)))
  1555. break;
  1556. DdeDisconnect( pMDI->hExeConv );
  1557. if (pMDI->hClpConv)
  1558. DdeDisconnect ( pMDI->hClpConv );
  1559. if (pMDI->hVClpConv)
  1560. DdeDisconnect ( pMDI->hVClpConv );
  1561. if (pMDI->hszConvPartner)
  1562. DdeFreeStringHandle ( idInst, pMDI->hszConvPartner );
  1563. if (pMDI->hszConvPartnerNP)
  1564. DdeFreeStringHandle ( idInst, pMDI->hszConvPartnerNP );
  1565. if (pMDI->hszClpTopic)
  1566. DdeFreeStringHandle ( idInst, pMDI->hszClpTopic );
  1567. if (pMDI->hszVClpTopic)
  1568. DdeFreeStringHandle ( idInst, pMDI->hszVClpTopic );
  1569. if (pMDI->pVClpbrd)
  1570. DestroyVClipboard ( pMDI->pVClpbrd );
  1571. if (hwnd == hwndLocal)
  1572. hwndLocal = NULL;
  1573. if (hwnd == hwndClpbrd)
  1574. hwndClpbrd = NULL;
  1575. // free up the MDI info struct
  1576. GlobalFree ( (HGLOBAL)pMDI );
  1577. break;
  1578. default:
  1579. return (DefMDIChildProc(hwnd, msg, wParam, lParam));
  1580. }
  1581. return 0L;
  1582. }
  1583. /****************************************************************************
  1584. *
  1585. * FUNCTION : SendMessageToKids
  1586. *
  1587. * PURPOSE : Send the given message with the given parameters to all
  1588. * of the MDI child windows.
  1589. *
  1590. * RETURNS : None.
  1591. *
  1592. ****************************************************************************/
  1593. VOID SendMessageToKids(
  1594. WORD msg,
  1595. WPARAM wParam,
  1596. LPARAM lParam)
  1597. {
  1598. register HWND hwndT;
  1599. hwndT = GetWindow (hwndMDIClient, GW_CHILD);
  1600. while (hwndT)
  1601. {
  1602. SendMessage (hwndT, msg, wParam, lParam);
  1603. hwndT = GetWindow(hwndT, GW_HWNDNEXT);
  1604. }
  1605. }
  1606. BOOL SyncOpenClipboard(
  1607. HWND hwnd)
  1608. {
  1609. BOOL fOK;
  1610. if (!fClpOpen)
  1611. {
  1612. // PINFO(TEXT("\r\nClipbook: Opening Clipboard\r\n"));
  1613. WaitForSingleObject(hmutexClp, 0); //INFINITE);
  1614. fOK = OpenClipboard(hwnd);
  1615. if (!fOK)
  1616. {
  1617. PERROR("OpenClipboard failed\r\n");
  1618. ReleaseMutex(hmutexClp);
  1619. }
  1620. else
  1621. {
  1622. fClpOpen = TRUE;
  1623. }
  1624. return fOK;
  1625. }
  1626. else
  1627. {
  1628. PERROR("Attempt at opening clipboard twice!\r\n");
  1629. return(FALSE);
  1630. }
  1631. return fOK;
  1632. }
  1633. BOOL SyncCloseClipboard (void)
  1634. {
  1635. BOOL fOK;
  1636. // PINFO(TEXT("\r\nClipbook: Closing Clipboard\r\n"));
  1637. fOK = CloseClipboard();
  1638. ReleaseMutex(hmutexClp);
  1639. if (!fOK)
  1640. {
  1641. PERROR("CloseClipboard failed\r\n");
  1642. }
  1643. fClpOpen = FALSE;
  1644. return fOK;
  1645. }