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.

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