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.

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