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.

1144 lines
31 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: Srvr.c Server Main module
  3. *
  4. * Purpose: Includes All the server communication related routines.
  5. *
  6. * Created: Oct 1990.
  7. *
  8. * Copyright (c) 1985, 1986, 1987, 1988, 1989 Microsoft Corporation
  9. *
  10. * History:
  11. * Raor: Wrote the original version.
  12. *
  13. *
  14. \***************************************************************************/
  15. #include <windows.h>
  16. #include <shellapi.h>
  17. #include "cmacs.h"
  18. #include "ole.h"
  19. #include "dde.h"
  20. #include "srvr.h"
  21. // LOWWORD - BYTE 0 major verision, BYTE1 minor version,
  22. // HIWORD is reserved
  23. #define OLE_VERSION 0x1001L
  24. extern ATOM aOLE;
  25. extern ATOM aSysTopic;
  26. extern ATOM aStdExit;
  27. extern ATOM aStdCreate;
  28. extern ATOM aStdOpen;
  29. extern ATOM aStdEdit;
  30. extern ATOM aStdCreateFromTemplate;
  31. extern ATOM aStdShowItem;
  32. extern ATOM aProtocols;
  33. extern ATOM aTopics;
  34. extern ATOM aFormats;
  35. extern ATOM aStatus;
  36. extern ATOM cfNative;
  37. extern ATOM aEditItems;
  38. extern ATOM aStdClose;
  39. extern HANDLE hdllInst;
  40. extern BOOL bProtMode;
  41. extern FARPROC lpTerminateClients;
  42. #ifdef FIREWALLS
  43. BOOL bShowed = FALSE;
  44. void ShowVersion (void);
  45. #endif
  46. DWORD FAR PASCAL OleQueryServerVersion ()
  47. {
  48. return OLE_VERSION;
  49. }
  50. /***************************** Public Function ****************************\
  51. * OLESTATUS FAR PASCAL OleRegisterServer (lpclass, lpolesrvr, lplhsrvr)
  52. *
  53. * OleRegisterServer: Registers the server with the server library.
  54. *
  55. * Parameters:
  56. * 1. Ptr to the server class.
  57. * 2. Ptr to the olesrvr. This is private to the server app.
  58. * (Typically this is the ptr to the private storage area of
  59. * server app server related info).
  60. * 3. Ptr to the LHSRVR. Place where to pass back the long
  61. * handle of the server in DLL (This is private to the DLL).
  62. *
  63. * return values:
  64. * returns OLE_OK if the server is successfully registered .
  65. * else returns the corresponding error.
  66. *
  67. *
  68. * History:
  69. * Raor: Wrote it,
  70. \***************************************************************************/
  71. OLESTATUS FAR PASCAL OleRegisterServer (lpclass, lpolesrvr, lplhsrvr, hInst, useFlags)
  72. LPCSTR lpclass; // class name
  73. LPOLESERVER lpolesrvr; // ole srvr(private to srvr app)
  74. LHSRVR FAR * lplhsrvr; // where we pass back our private handle
  75. HANDLE hInst;
  76. OLE_SERVER_USE useFlags;
  77. {
  78. HANDLE hsrvr = NULL;
  79. LPSRVR lpsrvr = NULL;
  80. ATOM aExe = NULL;
  81. Puts ("OleRegisterServer");
  82. if (!bProtMode)
  83. return OLE_ERROR_PROTECT_ONLY;
  84. PROBE_READ((LPSTR)lpclass);
  85. PROBE_WRITE(lpolesrvr);
  86. PROBE_WRITE(lplhsrvr);
  87. // add the app atom to global list
  88. if (!ValidateSrvrClass ((LPSTR)lpclass, &aExe))
  89. return OLE_ERROR_CLASS;
  90. hsrvr = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_DDESHARE, sizeof (SRVR));
  91. if (! (hsrvr && (lpsrvr = (LPSRVR)GlobalLock (hsrvr))))
  92. goto errReturn;
  93. // set the signature handle and the app atom.
  94. lpsrvr->sig[0] = 'S';
  95. lpsrvr->sig[1] = 'R';
  96. lpsrvr->hsrvr = hsrvr;
  97. lpsrvr->aClass = GlobalAddAtom (lpclass);
  98. lpsrvr->lpolesrvr = lpolesrvr;
  99. lpsrvr->relLock = TRUE; // set the release lock.
  100. lpsrvr->aExe = aExe;
  101. lpsrvr->useFlags = useFlags;
  102. #ifdef FIREWALLS
  103. ASSERT ((useFlags == OLE_SERVER_SINGLE || useFlags == OLE_SERVER_MULTI), "invalid server options");
  104. #endif
  105. // Create the servre window and do not show it.
  106. if (!(lpsrvr->hwnd = CreateWindow ("SrvrWndClass", "Srvr",
  107. WS_OVERLAPPED,0,0,0,0,NULL,NULL, hdllInst, NULL)))
  108. goto errReturn;
  109. // save the ptr to the srever struct in the window.
  110. SetWindowLong (lpsrvr->hwnd, 0, (LONG)lpsrvr);
  111. // Set the signature.
  112. SetWindowWord (lpsrvr->hwnd, WW_LE, WC_LE);
  113. SetWindowWord (lpsrvr->hwnd, WW_HANDLE, (WORD)hInst);
  114. *lplhsrvr = (LONG)lpsrvr;
  115. return OLE_OK;
  116. errReturn:
  117. if (lpsrvr){
  118. if (lpsrvr->hwnd)
  119. DestroyWindow (lpsrvr->hwnd);
  120. if (lpsrvr->aClass)
  121. GlobalDeleteAtom (lpsrvr->aClass);
  122. if (lpsrvr->aExe)
  123. GlobalDeleteAtom (lpsrvr->aExe);
  124. GlobalUnlock (hsrvr);
  125. }
  126. if (hsrvr)
  127. GlobalFree (hsrvr);
  128. return OLE_ERROR_MEMORY;
  129. }
  130. // ValidateSrvrClass checks whether the given server class is valid by
  131. // looking in the win.ini.
  132. BOOL INTERNAL ValidateSrvrClass (lpclass, lpAtom)
  133. LPSTR lpclass;
  134. ATOM FAR * lpAtom;
  135. {
  136. char buf[MAX_STR];
  137. LONG cb = MAX_STR;
  138. char key[MAX_STR];
  139. LPSTR lptmp;
  140. LPSTR lpbuf;
  141. char ch;
  142. lstrcpy (key, lpclass);
  143. lstrcat (key, "\\protocol\\StdFileEditing\\server");
  144. if (RegQueryValue (HKEY_CLASSES_ROOT, key, buf, &cb))
  145. return FALSE;
  146. if (!buf[0])
  147. return FALSE;
  148. // Get exe name without path and then get an atom for that
  149. lptmp = lpbuf = (LPSTR)buf;
  150. #if defined(FE_SB) //[J1]
  151. while ( ch = *lptmp ) { //[J1]
  152. lptmp = AnsiNext( lptmp ); //[J1]
  153. #else //[J1]
  154. while ((ch = *lptmp++) && ch != '\0') {
  155. #endif //[J1]
  156. if (ch == '\\' || ch == ':')
  157. lpbuf = lptmp;
  158. }
  159. *lpAtom = GlobalAddAtom (lpbuf);
  160. return TRUE;
  161. }
  162. /***************************** Public Function ****************************\
  163. * OLESTATUS FAR PASCAL OleRevokeServer (lhsrvr)
  164. *
  165. * OlerevokeServer: Unregisters the server which has been registered.
  166. *
  167. * Parameters:
  168. * 1. DLL server handle.
  169. *
  170. *
  171. * return values:
  172. * returns OLE_OK if the server is successfully unregisterd.
  173. * ( It is Ok for the app free the associated space).
  174. * If the unregistration is intiated, returns OLE_STARTED.
  175. * Calls the Server class release entry point when the server
  176. * can be released.
  177. *
  178. * History:
  179. * Raor: Wrote it,
  180. \***************************************************************************/
  181. OLESTATUS FAR PASCAL OleRevokeServer (lhsrvr)
  182. LHSRVR lhsrvr;
  183. {
  184. HWND hwndSrvr;
  185. LPSRVR lpsrvr;
  186. Puts ("OleRevokeServer");
  187. if (!CheckServer (lpsrvr = (LPSRVR)lhsrvr))
  188. return OLE_ERROR_HANDLE;
  189. if (lpsrvr->bTerminate && lpsrvr->termNo)
  190. return OLE_WAIT_FOR_RELEASE;
  191. hwndSrvr = lpsrvr->hwnd;
  192. #ifdef FIREWALLS
  193. ASSERT (hwndSrvr, "Illegal server handle ")
  194. #endif
  195. // Terminate the conversation with all clients.
  196. // If there are any clients to be terminated
  197. // return back with OLE_STARTED and srvr relase
  198. // will be called for releasing the server finally.
  199. // we are terminating.
  200. lpsrvr->bTerminate = TRUE;
  201. lpsrvr->termNo = 0;
  202. // send ack if Revoke is done as a result of StdExit
  203. if (lpsrvr->fAckExit) {
  204. // Post the acknowledge to the client
  205. if (!PostMessageToClient (lpsrvr->hwndExit, WM_DDE_ACK, lpsrvr->hwnd,
  206. MAKELONG (0x8000, lpsrvr->hDataExit)))
  207. // if the window died or post failed, delete the atom.
  208. GlobalFree (lpsrvr->hDataExit);
  209. }
  210. // revoks all the documents registered with this server.
  211. RevokeAllDocs (lpsrvr);
  212. // enumerate all the clients which are in your list and post the
  213. // termination.
  214. EnumProps (hwndSrvr, lpTerminateClients);
  215. // post all the messages with yield which have been collected in enum
  216. // UnblockPostMsgs (hwndSrvr, TRUE);
  217. // reset the release lock. Now it is ok to release the server
  218. // when all the doc clients and server clients have sent back the
  219. // termination.
  220. lpsrvr->relLock = FALSE;
  221. return ReleaseSrvr (lpsrvr);
  222. }
  223. // ReleaseSrvr: Called when ever a matching WM_TERMINATE is received
  224. // from doc clients or the server clients of a particular server.
  225. // If there are no more terminates pending, it is ok to release the server.
  226. // Calls the server app "release" proc for releasing the server.
  227. int INTERNAL ReleaseSrvr (lpsrvr)
  228. LPSRVR lpsrvr;
  229. {
  230. HANDLE hsrvr;
  231. // release srvr is called only when everything is
  232. // cleaned and srvr app can post WM_QUIT
  233. if (lpsrvr->bTerminate){
  234. // only if we are revoking server then see whether it is ok to
  235. // call Release.
  236. // First check whethere any docs are active.
  237. // Doc window is a child window for server window.
  238. if (lpsrvr->termNo || GetWindow (lpsrvr->hwnd, GW_CHILD))
  239. return OLE_WAIT_FOR_RELEASE;
  240. // if the block queue is not empty, do not quit
  241. if (!IsBlockQueueEmpty(lpsrvr->hwnd))
  242. return OLE_WAIT_FOR_RELEASE;
  243. }
  244. if (lpsrvr->relLock)
  245. return OLE_WAIT_FOR_RELEASE; // server is locked. So, delay releasing
  246. // Inform server app it is time to clean up and post WM_QUIT.
  247. #ifdef FIREWALLS
  248. if (!CheckPointer (lpsrvr->lpolesrvr, WRITE_ACCESS))
  249. ASSERT(0, "Invalid LPOLESERVER")
  250. else if (!CheckPointer (lpsrvr->lpolesrvr->lpvtbl, WRITE_ACCESS))
  251. ASSERT(0, "Invalid LPOLESERVERVTBL")
  252. else
  253. ASSERT (lpsrvr->lpolesrvr->lpvtbl->Release,
  254. "Invalid pointer to Release method")
  255. #endif
  256. (*lpsrvr->lpolesrvr->lpvtbl->Release)(lpsrvr->lpolesrvr);
  257. if (lpsrvr->aClass)
  258. GlobalDeleteAtom (lpsrvr->aClass);
  259. if (lpsrvr->aExe)
  260. GlobalDeleteAtom (lpsrvr->aExe);
  261. DestroyWindow (lpsrvr->hwnd);
  262. GlobalUnlock (hsrvr = lpsrvr->hsrvr);
  263. GlobalFree (hsrvr);
  264. return OLE_OK;
  265. }
  266. //TerminateClients: Call back for the enum properties.
  267. BOOL FAR PASCAL TerminateClients (hwnd, lpstr, hdata)
  268. HWND hwnd;
  269. LPSTR lpstr;
  270. HANDLE hdata;
  271. {
  272. LPSRVR lpsrvr;
  273. lpsrvr = (LPSRVR)GetWindowLong (hwnd, 0);
  274. // If the client already died, no terminate.
  275. if (IsWindowValid ((HWND)hdata)) {
  276. lpsrvr->termNo++;
  277. // irrespective of the post, incremet the count, so
  278. // that client does not die.
  279. PostMessageToClientWithBlock ((HWND)hdata, WM_DDE_TERMINATE, hwnd, NULL);
  280. }
  281. else
  282. ASSERT (FALSE, "TERMINATE: Client's System chanel is missing");
  283. return TRUE;
  284. }
  285. long FAR PASCAL SrvrWndProc (hwnd, msg, wParam, lParam)
  286. HWND hwnd;
  287. WORD msg;
  288. WORD wParam;
  289. LONG lParam;
  290. {
  291. LPSRVR lpsrvr;
  292. WORD status = NULL;
  293. HWND hwndClient;
  294. HANDLE hdata;
  295. OLESTATUS retval;
  296. if (AddMessage (hwnd, msg, wParam, lParam, WT_SRVR))
  297. return 0L;
  298. lpsrvr = (LPSRVR)GetWindowLong (hwnd, 0);
  299. switch (msg){
  300. case WM_TIMER:
  301. UnblockPostMsgs (hwnd, FALSE);
  302. // if no more blocked message empty the queue.
  303. if (IsBlockQueueEmpty (hwnd))
  304. KillTimer (hwnd, wParam);
  305. if (lpsrvr->bTerminate && IsBlockQueueEmpty(lpsrvr->hwnd))
  306. // Now see wheteher we can release the server .
  307. ReleaseSrvr (lpsrvr);
  308. break;
  309. case WM_CREATE:
  310. DEBUG_OUT ("Srvr create window", 0)
  311. break;
  312. case WM_DDE_INITIATE:
  313. #ifdef FIREWALLS
  314. ASSERT (lpsrvr, "No server window handle in server window");
  315. #endif
  316. DEBUG_OUT ("Srvr: DDE init",0);
  317. if (lpsrvr->bTerminate){
  318. DEBUG_OUT ("Srvr: No action due to termination process",0)
  319. break;
  320. }
  321. // class is not matching, so it is not definitely for us.
  322. // for apps sending the EXE for initiate, do not allow if the app
  323. // is mutiple server.
  324. if (!(lpsrvr->aClass == (ATOM)(LOWORD(lParam)) ||
  325. (lpsrvr->aExe == (ATOM)(LOWORD(lParam)) && IsSingleServerInstance ())))
  326. break;
  327. if (!HandleInitMsg (lpsrvr, lParam)) {
  328. if (!(aSysTopic == (ATOM)(HIWORD(lParam)))) {
  329. // if the server window is not the right window for
  330. // DDE conversation, then try with the doc windows.
  331. SendMsgToChildren (hwnd, msg, wParam, lParam);
  332. }
  333. break;
  334. }
  335. // We can enterain this client. Put him in our client list
  336. // and acknowledge the intiate.
  337. if (!AddClient (hwnd, (HWND)wParam, (HWND)wParam))
  338. break;
  339. lpsrvr->cClients++;
  340. lpsrvr->bnoRelease = FALSE;
  341. // add the atoms and post acknowledge
  342. DuplicateAtom (LOWORD(lParam));
  343. DuplicateAtom (HIWORD(lParam));
  344. SendMessage ((HWND)wParam, WM_DDE_ACK, (WORD)hwnd, lParam);
  345. break;
  346. case WM_DDE_EXECUTE:
  347. #ifdef FIREWALLS
  348. ASSERT (lpsrvr, "No server window handle in server window");
  349. #endif
  350. DEBUG_OUT ("srvr: execute", 0)
  351. #ifdef FIREWALLS
  352. // find the client in the client list.
  353. hwndClient = FindClient (lpsrvr->hwnd, (HWND)wParam);
  354. ASSERT (hwndClient, "Client is missing from the server")
  355. #endif
  356. // Are we terminating
  357. if (lpsrvr->bTerminate) {
  358. DEBUG_OUT ("Srvr: sys execute after terminate posted",0)
  359. // !!! are we supposed to free the data
  360. GlobalFree (HIWORD(lParam));
  361. break;
  362. }
  363. retval = SrvrExecute (hwnd, HIWORD (lParam), (HWND)wParam);
  364. SET_MSG_STATUS (retval, status)
  365. if (!lpsrvr->bTerminate) {
  366. // Post the acknowledge to the client
  367. if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, hwnd,
  368. MAKELONG (status, HIWORD(lParam))))
  369. // if the window died or post failed, delete the atom.
  370. GlobalFree (HIWORD(lParam));
  371. }
  372. break;
  373. case WM_DDE_TERMINATE:
  374. DEBUG_OUT ("Srvr: DDE terminate",0)
  375. #ifdef FIREWALLS
  376. // find the client in the client list.
  377. hwndClient = FindClient (lpsrvr->hwnd, (HWND)wParam);
  378. ASSERT (hwndClient, "Client is missing from the server")
  379. #endif
  380. DeleteClient (lpsrvr->hwnd, (HWND)wParam);
  381. lpsrvr->cClients--;
  382. if (lpsrvr->bTerminate){
  383. if ((--lpsrvr->termNo == 0) && (IsBlockQueueEmpty (lpsrvr->hwnd)))
  384. // Now see wheteher we can release the server .
  385. ReleaseSrvr (lpsrvr);
  386. // if we released the server, then
  387. // by the time we come here,, we have destroyed the window
  388. }else {
  389. // If client intiated the terminate. post matching terminate
  390. PostMessageToClient ((HWND)wParam, WM_DDE_TERMINATE,
  391. hwnd, NULL);
  392. // callback release tell the srvr app, it can exit if needs.
  393. // Inform server app it is time to clean up and post WM_QUIT.
  394. // only if no docs present.
  395. #if 0
  396. if (lpsrvr->cClients == 0
  397. && (GetWindow (lpsrvr->hwnd, GW_CHILD) == NULL)) {
  398. #endif
  399. if (QueryRelease (lpsrvr)){
  400. #ifdef FIREWALLS
  401. if (!CheckPointer (lpsrvr->lpolesrvr, WRITE_ACCESS))
  402. ASSERT (0, "Invalid LPOLESERVER")
  403. else if (!CheckPointer (lpsrvr->lpolesrvr->lpvtbl,
  404. WRITE_ACCESS))
  405. ASSERT (0, "Invalid LPOLESERVERVTBL")
  406. else
  407. ASSERT (lpsrvr->lpolesrvr->lpvtbl->Release,
  408. "Invalid pointer to Release method")
  409. #endif
  410. (*lpsrvr->lpolesrvr->lpvtbl->Release) (lpsrvr->lpolesrvr);
  411. }
  412. }
  413. break;
  414. case WM_DDE_REQUEST:
  415. if (lpsrvr->bTerminate || !IsWindowValid ((HWND) wParam))
  416. goto RequestErr;
  417. if(RequestDataStd (lParam, (HANDLE FAR *)&hdata) != OLE_OK){
  418. // if request failed, then acknowledge with error.
  419. if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, hwnd,
  420. MAKELONG(0x8000, HIWORD(lParam))))
  421. RequestErr:
  422. if (HIWORD(lParam))
  423. GlobalDeleteAtom (HIWORD(lParam));
  424. } else {
  425. // post the data message and we are not asking for any
  426. // acknowledge.
  427. if (!PostMessageToClient ((HWND)wParam, WM_DDE_DATA, hwnd,
  428. MAKELONG(hdata, HIWORD(lParam)))) {
  429. GlobalFree (hdata);
  430. goto RequestErr;
  431. }
  432. }
  433. break;
  434. case WM_DESTROY:
  435. DEBUG_OUT ("Srvr: Destroy window",0)
  436. break;
  437. default:
  438. DEBUG_OUT ("Srvr: Default message",0)
  439. return DefWindowProc (hwnd, msg, wParam, lParam);
  440. }
  441. return 0L;
  442. }
  443. BOOL INTERNAL HandleInitMsg (lpsrvr, lParam)
  444. LPSRVR lpsrvr;
  445. LONG lParam;
  446. {
  447. // If it is not system or Ole, this is not the server.
  448. if (!((aSysTopic == (ATOM)(HIWORD(lParam))) ||
  449. (aOLE == (ATOM)(HIWORD(lParam)))))
  450. return FALSE;
  451. // single instance MDI accept
  452. if (lpsrvr->useFlags == OLE_SERVER_SINGLE)
  453. return TRUE;
  454. // this server is multiple instance. So, check for any clients or docs.
  455. if (!GetWindow (lpsrvr->hwnd, GW_CHILD) && !lpsrvr->cClients)
  456. return TRUE;
  457. return FALSE;
  458. }
  459. // AddClient: Adds the client as property to the server
  460. // window. Key is the string generated from the window
  461. // handle and the data is the window itself.
  462. BOOL INTERNAL AddClient (hwnd, hkey, hdata)
  463. HWND hwnd;
  464. HANDLE hkey;
  465. HANDLE hdata;
  466. {
  467. char buf[6];
  468. MapToHexStr ((LPSTR)buf, hkey);
  469. return SetProp (hwnd, (LPSTR)buf, hdata);
  470. }
  471. //DeleteClient: deletes the client from the server clients list.
  472. BOOL INTERNAL DeleteClient (hwnd, hkey)
  473. HWND hwnd;
  474. HANDLE hkey;
  475. {
  476. char buf[6];
  477. MapToHexStr ((LPSTR)buf, hkey);
  478. return RemoveProp (hwnd, (LPSTR)buf);
  479. }
  480. // FindClient: Finds whether a given client is
  481. // in the server client list.
  482. HANDLE INTERNAL FindClient (hwnd, hkey)
  483. HWND hwnd;
  484. HANDLE hkey;
  485. {
  486. char buf[6];
  487. MapToHexStr ((LPSTR)buf, hkey);
  488. return GetProp (hwnd, (LPSTR)buf);
  489. }
  490. // SrvrExecute: takes care of the WM_DDE_EXEXCUTE for the
  491. // server.
  492. OLESTATUS INTERNAL SrvrExecute (hwnd, hdata, hwndClient)
  493. HWND hwnd;
  494. HANDLE hdata;
  495. HWND hwndClient;
  496. {
  497. ATOM aCmd;
  498. BOOL fActivate;
  499. LPSTR lpdata = NULL;
  500. HANDLE hdup = NULL;
  501. int retval = OLE_ERROR_MEMORY;
  502. LPSTR lpdocname;
  503. LPSTR lptemplate;
  504. LPOLESERVERDOC lpoledoc = NULL;
  505. LPDOC lpdoc = NULL;
  506. LPSRVR lpsrvr;
  507. LPOLESERVER lpolesrvr;
  508. LPSTR lpnextarg;
  509. LPSTR lpclassname;
  510. LPSTR lpitemname;
  511. LPSTR lpopt;
  512. char buf[MAX_STR];
  513. WORD wCmdType;
  514. // !!! this code can be lot simplified if we do the argument scanning
  515. // seperately and return the ptrs to the args. Rewrite later on.
  516. if (!(hdup = DuplicateData (hdata)))
  517. goto errRtn;
  518. if (!(lpdata = GlobalLock (hdup)))
  519. goto errRtn;
  520. DEBUG_OUT (lpdata, 0)
  521. lpsrvr = (LPSRVR)GetWindowLong (hwnd, 0);
  522. #ifdef FIREWALLS
  523. ASSERT (lpsrvr, "Srvr: srvr does not exist");
  524. #endif
  525. lpolesrvr = lpsrvr->lpolesrvr;
  526. #ifdef FIREWALLS
  527. ASSERT ((CheckPointer (lpolesrvr, WRITE_ACCESS)),
  528. "Srvr: lpolesrvr does not exist");
  529. #endif
  530. if (*lpdata++ != '[') // commands start with the left sqaure bracket
  531. goto errRtn;
  532. retval = OLE_ERROR_SYNTAX;
  533. // scan upto the first arg
  534. if (!(wCmdType = ScanCommand (lpdata, WT_SRVR, &lpdocname, &aCmd)))
  535. goto errRtn;
  536. if (wCmdType == NON_OLE_COMMAND) {
  537. if (!UtilQueryProtocol (lpsrvr->aClass, PROTOCOL_EXECUTE))
  538. retval = OLE_ERROR_PROTOCOL;
  539. else {
  540. #ifdef FIREWALLS
  541. if (!CheckPointer (lpolesrvr->lpvtbl, WRITE_ACCESS))
  542. ASSERT (0, "Invalid LPOLESERVERVTBL")
  543. else
  544. ASSERT (lpolesrvr->lpvtbl->Execute,
  545. "Invalid pointer to Exit method")
  546. #endif
  547. retval = (*lpolesrvr->lpvtbl->Execute) (lpolesrvr, hdata);
  548. }
  549. goto errRtn1;
  550. }
  551. if (aCmd == aStdExit){
  552. if (*lpdocname)
  553. goto errRtn1;
  554. #ifdef FIREWALLS
  555. if (!CheckPointer (lpolesrvr->lpvtbl, WRITE_ACCESS))
  556. ASSERT (0, "Invalid LPOLESERVERVTBL")
  557. else
  558. ASSERT (lpolesrvr->lpvtbl->Exit, "Invalid pointer to Exit method")
  559. #endif
  560. lpsrvr->fAckExit = TRUE;
  561. lpsrvr->hwndExit = hwndClient;
  562. lpsrvr->hDataExit = hdata;
  563. retval = (*lpolesrvr->lpvtbl->Exit) (lpolesrvr);
  564. lpsrvr->fAckExit = FALSE;
  565. goto end2;
  566. }
  567. // scan the next argument.
  568. if (!(lpnextarg = ScanArg(lpdocname)))
  569. goto errRtn;
  570. //////////////////////////////////////////////////////////////////////////
  571. //
  572. // [StdShowItem("docname", "itemname"[, "true"])]
  573. //
  574. //////////////////////////////////////////////////////////////////////////
  575. if (aCmd == aStdShowItem) {
  576. // first find the documnet. If the doc does not exist, then
  577. // blow it off.
  578. if (!(lpdoc = FindDoc (lpsrvr, lpdocname)))
  579. goto errRtn1;
  580. lpitemname = lpnextarg;
  581. if( !(lpopt = ScanArg(lpitemname)))
  582. goto errRtn1;
  583. // scan for the optional parameter
  584. // Optional can be only TRUE or FALSE.
  585. fActivate = FALSE;
  586. if (*lpopt) {
  587. if( !(lpnextarg = ScanBoolArg (lpopt, (BOOL FAR *)&fActivate)))
  588. goto errRtn1;
  589. if (*lpnextarg)
  590. goto errRtn1;
  591. }
  592. // scan it. But, igonre the arg.
  593. retval = DocShowItem (lpdoc, lpitemname, !fActivate);
  594. goto end2;
  595. }
  596. //////////////////////////////////////////////////////////////////////////
  597. //
  598. // [StdCloseDocument ("docname")]
  599. //
  600. //////////////////////////////////////////////////////////////////////////
  601. if (aCmd == aStdClose) {
  602. if (!(lpdoc = FindDoc (lpsrvr, lpdocname)))
  603. goto errRtn1;
  604. if (*lpnextarg)
  605. goto errRtn1;
  606. #ifdef FIREWALLS
  607. if (!CheckPointer (lpdoc->lpoledoc, WRITE_ACCESS))
  608. ASSERT (0, "Invalid LPOLESERVERDOC")
  609. else if (!CheckPointer (lpdoc->lpoledoc->lpvtbl, WRITE_ACCESS))
  610. ASSERT (0, "Invalid LPOLESERVERDOCVTBL")
  611. else
  612. ASSERT (lpdoc->lpoledoc->lpvtbl->Close,
  613. "Invalid pointer to Close method")
  614. #endif
  615. retval = (*lpdoc->lpoledoc->lpvtbl->Close)(lpdoc->lpoledoc);
  616. goto end2;
  617. }
  618. if (aCmd == aStdOpen) {
  619. // find if any document is already open.
  620. // if the doc is open, then no need to call srvr app.
  621. if (FindDoc (lpsrvr, lpdocname)){
  622. retval = OLE_OK;
  623. goto end1;
  624. }
  625. }
  626. if (aCmd == aStdCreate || aCmd == aStdCreateFromTemplate) {
  627. lpclassname = lpdocname;
  628. lpdocname = lpnextarg;
  629. if( !(lpnextarg = ScanArg(lpdocname)))
  630. goto errRtn1;
  631. }
  632. // check whether we can create/open more than one doc.
  633. if ((lpsrvr->useFlags == OLE_SERVER_MULTI) &&
  634. GetWindow (lpsrvr->hwnd, GW_CHILD))
  635. goto errRtn;
  636. // No Doc. register the document. lpoledoc is being probed
  637. // for validity. So, pass some writeable ptr. It is not
  638. // being used to access anything yet
  639. if (OleRegisterServerDoc ((LHSRVR)lpsrvr, lpdocname,
  640. (LPOLESERVERDOC)NULL, (LHDOC FAR *)&lpdoc))
  641. goto errRtn;
  642. //////////////////////////////////////////////////////////////////////////
  643. //
  644. // [StdOpenDocument ("docname")]
  645. //
  646. //////////////////////////////////////////////////////////////////////////
  647. // Documnet does not exit.
  648. if(aCmd == aStdOpen) {
  649. #ifdef FIREWALLS
  650. if (!CheckPointer (lpolesrvr->lpvtbl, WRITE_ACCESS))
  651. ASSERT (0, "Invalid LPOLESERVERVTBL")
  652. else
  653. ASSERT (lpolesrvr->lpvtbl->Open, "Invalid pointer to Open method")
  654. #endif
  655. retval = (*lpolesrvr->lpvtbl->Open)(lpolesrvr, (LHDOC)lpdoc,
  656. lpdocname, (LPOLESERVERDOC FAR *) &lpoledoc);
  657. goto end;
  658. }
  659. else {
  660. lpdoc->fEmbed = TRUE;
  661. }
  662. //////////////////////////////////////////////////////////////////////////
  663. //
  664. // [StdNewDocument ("classname", "docname")]
  665. //
  666. //////////////////////////////////////////////////////////////////////////
  667. if (aCmd == aStdCreate) {
  668. #ifdef FIREWALLS
  669. if (!CheckPointer (lpolesrvr->lpvtbl, WRITE_ACCESS))
  670. ASSERT (0, "Invalid LPOLESERVERVTBL")
  671. else
  672. ASSERT (lpolesrvr->lpvtbl->Create,
  673. "Invalid pointer to Create method")
  674. #endif
  675. retval = (*lpolesrvr->lpvtbl->Create) (lpolesrvr, (LHDOC)lpdoc,
  676. lpclassname, lpdocname,
  677. (LPOLESERVERDOC FAR *) &lpoledoc);
  678. goto end;
  679. }
  680. //////////////////////////////////////////////////////////////////////////
  681. //
  682. // [StdEditDocument ("docname")]
  683. //
  684. //////////////////////////////////////////////////////////////////////////
  685. if (aCmd == aStdEdit){
  686. GlobalGetAtomName (lpsrvr->aClass, (LPSTR)buf, MAX_STR);
  687. #ifdef FIREWALLS
  688. if (!CheckPointer (lpolesrvr->lpvtbl, WRITE_ACCESS))
  689. ASSERT (0, "Invalid LPOLESERVERVTBL")
  690. else
  691. ASSERT (lpolesrvr->lpvtbl->Edit, "Invalid pointer to Edit method")
  692. #endif
  693. retval = (*lpolesrvr->lpvtbl->Edit) (lpolesrvr, (LHDOC)lpdoc,
  694. (LPSTR)buf, lpdocname,
  695. (LPOLESERVERDOC FAR *) &lpoledoc);
  696. goto end;
  697. }
  698. //////////////////////////////////////////////////////////////////////////
  699. //
  700. // [StdNewFormTemplate ("classname", "docname". "templatename)]
  701. //
  702. //////////////////////////////////////////////////////////////////////////
  703. if (aCmd == aStdCreateFromTemplate){
  704. lptemplate = lpnextarg;
  705. if(!(lpnextarg = ScanArg(lpnextarg)))
  706. goto errRtn;
  707. #ifdef FIREWALLS
  708. if (!CheckPointer (lpolesrvr->lpvtbl, WRITE_ACCESS))
  709. ASSERT (0, "Invalid LPOLESERVERVTBL")
  710. else
  711. ASSERT (lpolesrvr->lpvtbl->CreateFromTemplate,
  712. "Invalid pointer to CreateFromTemplate method")
  713. #endif
  714. retval = (*lpolesrvr->lpvtbl->CreateFromTemplate)(lpolesrvr,
  715. (LHDOC)lpdoc, lpclassname, lpdocname, lptemplate,
  716. (LPOLESERVERDOC FAR *) &lpoledoc);
  717. goto end;
  718. }
  719. DEBUG_OUT ("Unknown command", 0);
  720. end:
  721. if (retval != OLE_OK)
  722. goto errRtn;
  723. // Successful execute. remember the server app private doc handle here.
  724. lpdoc->lpoledoc = lpoledoc;
  725. end1:
  726. // make sure that the srg string is indeed terminated by
  727. // NULL.
  728. if (*lpnextarg)
  729. retval = OLE_ERROR_SYNTAX;
  730. errRtn:
  731. if ( retval != OLE_OK){
  732. // delete the oledoc structure
  733. if (lpdoc)
  734. OleRevokeServerDoc ((LHDOC)lpdoc);
  735. }
  736. end2:
  737. errRtn1:
  738. if (lpdata)
  739. GlobalUnlock (hdup);
  740. if (hdup)
  741. GlobalFree (hdup);
  742. if (retval == OLE_OK)
  743. lpsrvr->bnoRelease = TRUE;
  744. return retval;
  745. }
  746. void SendMsgToChildren (hwnd, msg, wParam, lParam)
  747. HWND hwnd;
  748. WORD msg;
  749. WORD wParam;
  750. LONG lParam;
  751. {
  752. hwnd = GetWindow(hwnd, GW_CHILD);
  753. while (hwnd) {
  754. SendMessage (hwnd, msg, wParam, lParam);
  755. hwnd = GetWindow (hwnd, GW_HWNDNEXT);
  756. }
  757. }
  758. OLESTATUS INTERNAL RequestDataStd (lparam, lphdde)
  759. LONG lparam;
  760. LPHANDLE lphdde;
  761. {
  762. char buf[MAX_STR];
  763. ATOM item;
  764. HANDLE hnew = NULL;
  765. if (!(item = (ATOM)(HIWORD (lparam))))
  766. goto errRtn;
  767. GlobalGetAtomName (item, (LPSTR)buf, MAX_STR);
  768. if (item == aEditItems){
  769. hnew = MakeGlobal ((LPSTR)"StdHostNames\tStdDocDimensions\tStdTargetDevice");
  770. goto PostData;
  771. }
  772. if (item == aProtocols) {
  773. hnew = MakeGlobal ((LPSTR)"Embedding\tStdFileEditing");
  774. goto PostData;
  775. }
  776. if (item == aTopics) {
  777. hnew = MakeGlobal ((LPSTR)"Doc");
  778. goto PostData;
  779. }
  780. if (item == aFormats) {
  781. hnew = MakeGlobal ((LPSTR)"Picture\tBitmap");
  782. goto PostData;
  783. }
  784. if (item == aStatus) {
  785. hnew = MakeGlobal ((LPSTR)"Ready");
  786. goto PostData;
  787. }
  788. // format we do not understand.
  789. goto errRtn;
  790. PostData:
  791. // Duplicate the DDE data
  792. if (MakeDDEData (hnew, CF_TEXT, lphdde, TRUE)){
  793. // !!! why are we duplicating the atom.
  794. DuplicateAtom ((ATOM)(HIWORD (lparam)));
  795. return OLE_OK;
  796. }
  797. errRtn:
  798. return OLE_ERROR_MEMORY;
  799. }
  800. BOOL INTERNAL QueryRelease (lpsrvr)
  801. LPSRVR lpsrvr;
  802. {
  803. HWND hwnd;
  804. LPDOC lpdoc;
  805. // Incase the terminate is called immediately after
  806. // the Std at sys level clear this.
  807. if (lpsrvr->bnoRelease) {
  808. lpsrvr->bnoRelease = FALSE;
  809. return FALSE;
  810. }
  811. if (lpsrvr->cClients)
  812. return FALSE;
  813. hwnd = GetWindow (lpsrvr->hwnd, GW_CHILD);
  814. // if either the server or the doc has any clients
  815. // return FALSE;
  816. while (hwnd){
  817. lpdoc = (LPDOC)GetWindowLong (hwnd, 0);
  818. if (lpdoc->cClients)
  819. return FALSE;
  820. hwnd = GetWindow (hwnd, GW_HWNDNEXT);
  821. }
  822. return TRUE;
  823. }
  824. //IsSingleServerInstance: returns true if the app is single server app else
  825. //false.
  826. BOOL INTERNAL IsSingleServerInstance ()
  827. {
  828. HWND hwnd;
  829. WORD cnt = 0;
  830. HANDLE hTask;
  831. char buf[MAX_STR];
  832. hwnd = GetWindow (GetDesktopWindow(), GW_CHILD);
  833. hTask = GetCurrentTask();
  834. while (hwnd) {
  835. if (hTask == GetWindowTask (hwnd)) {
  836. GetClassName (hwnd, (LPSTR)buf, MAX_STR);
  837. if (lstrcmp ((LPSTR)buf, SRVR_CLASS) == 0)
  838. cnt++;
  839. }
  840. hwnd = GetWindow (hwnd, GW_HWNDNEXT);
  841. }
  842. #ifdef FIREWALLS
  843. ASSERT (cnt > 0, "srvr window instance count is zero");
  844. #endif
  845. if (cnt == 1)
  846. return TRUE;
  847. else
  848. return FALSE;
  849. }