Source code of Windows XP (NT5)
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.

612 lines
17 KiB

  1. /*
  2. * utility.c - general purpose utility routines
  3. *
  4. * Created by Microsoft Corporation.
  5. * (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
  6. *
  7. */
  8. //*** INCLUDES ****
  9. #include <windows.h>
  10. #include <ole.h>
  11. #include "global.h"
  12. #include "demorc.h"
  13. #include "utility.h"
  14. #include "object.h"
  15. #include "dialog.h"
  16. static INT iTimerID = 0;
  17. static APPITEMPTR lpaItemHold;
  18. /****************************************************************************
  19. * ErrorMessage()
  20. *
  21. * Display a message box containing the specified string from the table.
  22. *
  23. * id WORD - Index into string table.
  24. ***************************************************************************/
  25. VOID FAR ErrorMessage( //* ENTRY:
  26. DWORD id //* message ID
  27. ){ //* LOCAL:
  28. CHAR sz[CBMESSAGEMAX]; //* string
  29. HWND hwnd; //* parent window handle
  30. if (IsWindow(hwndProp))
  31. hwnd = hwndProp;
  32. else if (IsWindow(hwndFrame))
  33. hwnd = hwndFrame;
  34. else
  35. return;
  36. LoadString(hInst, id, sz, CBMESSAGEMAX);
  37. MessageBox(hwnd, sz, szAppName, MB_OK | MB_ICONEXCLAMATION);
  38. }
  39. /****************************************************************************
  40. * Hourglass()
  41. *
  42. * Put up or takes down the hourglass cursor as needed.
  43. *
  44. * int bToggle - TRUE turns the hour glass on
  45. * HG_OFF turn it off
  46. ***************************************************************************/
  47. VOID FAR Hourglass( //* ENTRY:
  48. BOOL bOn //* hourglass on/off
  49. ){ //* LOCAL:
  50. static HCURSOR hcurWait = NULL; //* hourglass cursor
  51. static HCURSOR hcurSaved; //* old cursor
  52. static iCount = 0;
  53. if (bOn)
  54. {
  55. iCount++;
  56. if (!hcurWait)
  57. hcurWait = LoadCursor(NULL, IDC_WAIT);
  58. if (!hcurSaved)
  59. hcurSaved = SetCursor(hcurWait);
  60. }
  61. else if (!bOn)
  62. {
  63. if (--iCount < 0 )
  64. iCount = 0;
  65. else if (!iCount)
  66. {
  67. SetCursor(hcurSaved);
  68. hcurSaved = NULL;
  69. }
  70. }
  71. }
  72. /***************************************************************************
  73. * WaitForObject()
  74. *
  75. * Dispatch messagee until the specified object is not busy.
  76. * This allows asynchronous processing to occur.
  77. *
  78. * lpObject LPOLEOBJECT - pointer to object
  79. **************************************************************************/
  80. void FAR WaitForObject( //* ENTRY:
  81. APPITEMPTR paItem //* pointer to OLE object
  82. ){ //* LOCAL
  83. BOOL bTimerOn = FALSE;
  84. while (OleQueryReleaseStatus(paItem->lpObject) == OLE_BUSY)
  85. {
  86. lpaItemHold = paItem;
  87. if (!bTimerOn)
  88. bTimerOn = ToggleBlockTimer(TRUE);//* set timer
  89. ProcessMessage(hwndFrame, hAccTable);
  90. }
  91. if (bTimerOn)
  92. ToggleBlockTimer(FALSE);//* toggle timer off
  93. }
  94. /***************************************************************************
  95. * WaitForAllObjects()
  96. *
  97. * Wait for all asynchronous operations to complete.
  98. **************************************************************************/
  99. VOID FAR WaitForAllObjects(VOID)
  100. {
  101. BOOL bTimerOn = FALSE;
  102. while (cOleWait)
  103. {
  104. if (!bTimerOn)
  105. bTimerOn = ToggleBlockTimer(TRUE);//* set timer
  106. ProcessMessage(hwndFrame, hAccTable) ;
  107. }
  108. if (bTimerOn)
  109. ToggleBlockTimer(FALSE);//* toggle timer off
  110. }
  111. /****************************************************************************
  112. * ProcessMessage()
  113. *
  114. * Obtain and dispatch a message. Used when in a message dispatch loop.
  115. *
  116. * Returns BOOL - TRUE if message other than WM_QUIT retrieved
  117. * FALSE if WM_QUIT retrieved.
  118. ***************************************************************************/
  119. BOOL FAR ProcessMessage( //* ENTRY:
  120. HWND hwndFrame, //* main window handle
  121. HANDLE hAccTable //* accelerator table handle
  122. ){ //* LOCAL:
  123. BOOL fReturn; //* return value
  124. MSG msg; //* message
  125. if (fReturn = GetMessage(&msg, NULL, 0, 0))
  126. {
  127. if (cOleWait || !TranslateAccelerator(hwndFrame, hAccTable, &msg))
  128. {
  129. TranslateMessage(&msg);
  130. DispatchMessage(&msg);
  131. }
  132. }
  133. return fReturn;
  134. }
  135. /****************************************************************************
  136. * Dirty()
  137. *
  138. * Keep track of weather modifications have been made
  139. * to the document or not.
  140. *
  141. * iAction - action type:
  142. * DOC_CLEAN set document clean flag true
  143. * DOC_DIRTY the opposite
  144. * DOC_UNDIRTY undo one dirty op
  145. * DOC_QUERY return present state
  146. *
  147. * Returs int - present value of fDirty; 0 is clean.
  148. ***************************************************************************/
  149. INT FAR Dirty( //* ENTRY:
  150. INT iAction //* see above comment
  151. ){ //* LOCAL:
  152. static INT iDirty = 0; //* dirty state >0 is dirty
  153. switch (iAction)
  154. {
  155. case DOC_CLEAN:
  156. iDirty = 0;
  157. break;
  158. case DOC_DIRTY:
  159. iDirty++;
  160. break;
  161. case DOC_UNDIRTY:
  162. iDirty--;
  163. break;
  164. case DOC_QUERY:
  165. break;
  166. }
  167. return(iDirty);
  168. }
  169. /***************************************************************************
  170. * ObjectsBusy()
  171. *
  172. * This function enumerates the OLE objects in the current document
  173. * and displays a message box stating whether an object is busy.
  174. * This function calls the DisplayBusyMessage() function which
  175. * performs most of the work. This function is only used by the macro
  176. * BUSY_CHECK(), defined in object.h.
  177. *
  178. * fSelectionOnly BOOL -NOT USED?
  179. *
  180. * BOOL - TRUE if one or more objects found to be busy
  181. * FALSE otherwise
  182. *
  183. ***************************************************************************/
  184. BOOL FAR ObjectsBusy ()
  185. {
  186. APPITEMPTR pItem;
  187. if (iTimerID)
  188. {
  189. RetryMessage(NULL,RD_CANCEL);
  190. return TRUE;
  191. }
  192. for (pItem = GetTopItem(); pItem; pItem = GetNextItem(pItem))
  193. if (DisplayBusyMessage(pItem))
  194. return TRUE;
  195. return FALSE;
  196. }
  197. /***************************************************************************
  198. * DisplayBusyMessage()
  199. *
  200. * This function determines if an object is busy and displays
  201. * a message box stating this status.
  202. *
  203. * Returns BOOL - TRUE if object is busy
  204. **************************************************************************/
  205. BOOL FAR DisplayBusyMessage ( //* ENTRY:
  206. APPITEMPTR paItem //* application item pointer
  207. ){ //* LOCAL:
  208. if (OleQueryReleaseStatus(paItem->lpObject) == OLE_BUSY)
  209. {
  210. RetryMessage(paItem,RD_CANCEL);
  211. return TRUE;
  212. }
  213. return FALSE;
  214. }
  215. /***************************************************************************
  216. * CreateNewUniqueName()
  217. *
  218. * Create a string name unique to this document. This is done by using the
  219. * prefix string("OleDemo #") and appending a counter to the end of the
  220. * prefix string. The counter is incremented whenever a new object is added.
  221. * String will be 14 bytes long.
  222. *
  223. * Return LPSTR - pointer to unique object name.
  224. ***************************************************************************/
  225. LPSTR FAR CreateNewUniqueName( //* ENTRY:
  226. LPSTR lpstr //* destination pointer
  227. ){
  228. wsprintf( lpstr, "%s%04d", OBJPREFIX, iObjectNumber++ );
  229. return( lpstr );
  230. }
  231. /***************************************************************************
  232. * ValidateName()
  233. *
  234. * This function ensures that the given object name is valid and unique.
  235. *
  236. * Returns: BOOL - TRUE if object name valid
  237. **************************************************************************/
  238. BOOL FAR ValidateName( //* ENTRY:
  239. LPSTR lpstr //* pointer to object name
  240. ){ //* LOCAL:
  241. LPSTR lp; //* worker string
  242. INT n;
  243. //* check for "OleDemo #" prefix
  244. lp = OBJPREFIX;
  245. while( *lp )
  246. {
  247. if( *lpstr != *lp )
  248. return( FALSE );
  249. lpstr++; lp++;
  250. }
  251. //* convert string number to int
  252. for (n = 0 ; *lpstr ; n = n*10 + (*lpstr - '0'),lpstr++);
  253. if( n > 9999 ) //* 9999 is largest legal number
  254. return FALSE;
  255. if( iObjectNumber <= n) //* Make count > than any current
  256. iObjectNumber = n + 1; //* object to ensure uniqueness
  257. return TRUE;
  258. }
  259. /***************************************************************************
  260. * FreeAppItem()
  261. *
  262. * Free application item structure and destroy the associated structure.
  263. **************************************************************************/
  264. VOID FAR FreeAppItem( //* ENTRY:
  265. APPITEMPTR pItem //* pointer to application item
  266. ){ //* LOCAL:
  267. HANDLE hWork; //* handle used to free
  268. if (pItem)
  269. { //* destroy the window
  270. if (pItem->hwnd)
  271. DestroyWindow(pItem->hwnd);
  272. hWork = LocalHandle((LPSTR)pItem);//* get handle from pointer
  273. if (pItem->aLinkName)
  274. DeleteAtom(pItem->aLinkName);
  275. if (pItem->aServer)
  276. DeleteAtom(pItem->aServer);
  277. LocalUnlock(hWork);
  278. LocalFree(hWork);
  279. }
  280. }
  281. /***************************************************************************
  282. * SizeOfLinkData()
  283. *
  284. * Find the size of a linkdata string.
  285. **************************************************************************/
  286. LONG FAR SizeOfLinkData( //* ENTRY:
  287. LPSTR lpData //* pointer to link data
  288. ){ //* LOCAL:
  289. LONG lSize; //* total size
  290. lSize = (LONG)lstrlen(lpData)+1; //* get size of classname
  291. lSize += (LONG)lstrlen(lpData+lSize)+1; //* get size of doc.
  292. lSize += (LONG)lstrlen(lpData+lSize)+2;//* get size of item
  293. return lSize;
  294. }
  295. /****************************************************************************
  296. * ShowDoc()
  297. *
  298. * Display all the child windows associated with a document, or make all the
  299. * child windows hidden.
  300. ***************************************************************************/
  301. VOID FAR ShowDoc( //* ENTRY:
  302. LHCLIENTDOC lhcDoc, //* document handle
  303. INT iShow //* show/hide
  304. ){ //* LOCAL:
  305. APPITEMPTR pItem; //* application item pointer
  306. APPITEMPTR pItemTop = NULL;
  307. for (pItem = GetTopItem(); pItem; pItem = GetNextItem(pItem))
  308. {
  309. if (pItem->lhcDoc == lhcDoc)
  310. {
  311. if (!pItemTop)
  312. pItemTop = pItem;
  313. ShowWindow(pItem->hwnd,(iShow ? SW_SHOW : SW_HIDE));
  314. pItem->fVisible = (BOOL)iShow;
  315. }
  316. }
  317. if (pItemTop)
  318. SetTopItem(pItemTop);
  319. }
  320. /****************************************************************************
  321. * GetNextActiveItem()
  322. *
  323. * Returns HWND - the next visible window.
  324. ***************************************************************************/
  325. APPITEMPTR FAR GetNextActiveItem()
  326. { //* LOCAL:
  327. APPITEMPTR pItem; //* application item pointer
  328. for (pItem = GetTopItem(); pItem; pItem = GetNextItem(pItem))
  329. if (pItem->fVisible)
  330. break;
  331. return pItem;
  332. }
  333. /****************************************************************************
  334. * GetTopItem()
  335. ***************************************************************************/
  336. APPITEMPTR FAR GetTopItem()
  337. {
  338. HWND hwnd;
  339. if (hwnd = GetTopWindow(hwndFrame))
  340. return ((APPITEMPTR)GetWindowLong(hwnd,0));
  341. else
  342. return NULL;
  343. }
  344. /****************************************************************************
  345. * GetNextItem()
  346. ***************************************************************************/
  347. APPITEMPTR FAR GetNextItem( //* ENTRY:
  348. APPITEMPTR pItem //* application item pointer
  349. ){ //* LOCAL:
  350. HWND hwnd; //* next item window handle
  351. if (hwnd = GetNextWindow(pItem->hwnd, GW_HWNDNEXT))
  352. return((APPITEMPTR)GetWindowLong(hwnd,0));
  353. else
  354. return NULL;
  355. }
  356. /****************************************************************************
  357. * SetTopItem()
  358. ***************************************************************************/
  359. VOID FAR SetTopItem(
  360. APPITEMPTR pItem
  361. ){
  362. APPITEMPTR pLastItem;
  363. pLastItem = GetTopItem();
  364. if (pLastItem && pLastItem != pItem)
  365. SendMessage(pLastItem->hwnd,WM_NCACTIVATE, 0, 0L);
  366. if (!pItem)
  367. return;
  368. if (pItem->fVisible)
  369. {
  370. BringWindowToTop(pItem->hwnd);
  371. SendMessage(pItem->hwnd,WM_NCACTIVATE, 1, 0L);
  372. }
  373. }
  374. /***************************************************************************
  375. * ReallocLinkData()
  376. *
  377. * Reallocate link data in order to avoid creating lots and lots of global
  378. * memory thunks.
  379. **************************************************************************/
  380. BOOL FAR ReallocLinkData( //* ENTRY:
  381. APPITEMPTR pItem, //* application item pointer
  382. LONG lSize //* new link data size
  383. ){ //* LOCAL:
  384. HANDLE handle; //* temporary memory handle
  385. handle = GlobalHandle(pItem->lpLinkData);
  386. GlobalUnlock(handle);
  387. if (!(pItem->lpLinkData = GlobalLock(GlobalReAlloc(handle, lSize, 0))))
  388. {
  389. ErrorMessage(E_FAILED_TO_ALLOC);
  390. return FALSE;
  391. }
  392. return TRUE;
  393. }
  394. /***************************************************************************
  395. * AllocLinkData()
  396. *
  397. * Allocate link data space.
  398. **************************************************************************/
  399. BOOL FAR AllocLinkData( //* ENTRY:
  400. APPITEMPTR pItem, //* application item pointer
  401. LONG lSize //* link data size
  402. ){
  403. if (!(pItem->lpLinkData = GlobalLock(
  404. GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT ,lSize)
  405. )))
  406. {
  407. ErrorMessage(E_FAILED_TO_ALLOC);
  408. return FALSE;
  409. }
  410. return TRUE;
  411. }
  412. /***************************************************************************
  413. * FreeLinkData()
  414. *
  415. * Free the space associated with a linkdata pointer.
  416. **************************************************************************/
  417. VOID FAR FreeLinkData( //* ENTRY:
  418. LPSTR lpLinkData //* pointer to linkdata
  419. ){ //* LOCAL:
  420. HANDLE handle; //* temporary memory handle
  421. if (lpLinkData)
  422. {
  423. handle = GlobalHandle(lpLinkData);
  424. GlobalUnlock(handle);
  425. GlobalFree(handle);
  426. }
  427. }
  428. /****************************************************************************
  429. * ShowNewWindow()
  430. *
  431. * Show a new application item window.
  432. ***************************************************************************/
  433. VOID FAR ShowNewWindow( //* ENTRY:
  434. APPITEMPTR pItem
  435. ){
  436. if (pItem->fVisible)
  437. {
  438. pItem->fNew = TRUE;
  439. SetTopItem(pItem);
  440. ShowWindow(pItem->hwnd,SW_SHOW);
  441. }
  442. else
  443. ObjDelete(pItem,OLE_OBJ_DELETE);
  444. }
  445. /****************************************************************************
  446. * UnqualifyPath()
  447. *
  448. * return pointer to unqualified path name.
  449. ***************************************************************************/
  450. PSTR FAR UnqualifyPath(PSTR pPath)
  451. {
  452. PSTR pReturn;
  453. for (pReturn = pPath; *pPath; pPath++)
  454. if (*pPath == ':' || *pPath == '\\')
  455. pReturn = pPath+1;
  456. return pReturn;
  457. }
  458. /****************************************************************************
  459. * ToggleBlockTimer()
  460. *
  461. * Toggle a timer used to check for blocked servers.
  462. ***************************************************************************/
  463. BOOL FAR ToggleBlockTimer(BOOL bSet)
  464. {
  465. if (bSet && !iTimerID)
  466. {
  467. if (iTimerID = SetTimer(hwndFrame,1, 3000, (TIMERPROC) fnTimerBlockProc))
  468. return TRUE;
  469. }
  470. else if (iTimerID)
  471. {
  472. KillTimer(hwndFrame,1);
  473. iTimerID = 0;
  474. return TRUE;
  475. }
  476. return FALSE;
  477. }
  478. /****************************************************************************
  479. * fnTimerBlockProc()
  480. *
  481. * Timer callback procedure
  482. ***************************************************************************/
  483. VOID CALLBACK fnTimerBlockProc( //* ENTRY:
  484. HWND hWnd,
  485. UINT wMsg,
  486. UINT iTimerID,
  487. DWORD dwTime
  488. ){
  489. if (!hRetry)
  490. RetryMessage(lpaItemHold, RD_RETRY | RD_CANCEL);
  491. }