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.

1856 lines
42 KiB

  1. #include <windows.h>
  2. #include <port1632.h>
  3. #include <ddeml.h>
  4. #include "wrapper.h"
  5. #include "ddestrs.h"
  6. VOID PaintTest(HWND,PAINTSTRUCT *);
  7. HWND CreateButton(HWND);
  8. HANDLE hExtraMem=0;
  9. LPSTR pszNetName=NULL;
  10. HANDLE hmemNet=NULL;
  11. BOOL fnoClose=TRUE;
  12. LONG FAR PASCAL MainWndProc(
  13. HWND hwnd,
  14. UINT message,
  15. WPARAM wParam,
  16. LONG lParam)
  17. {
  18. PAINTSTRUCT ps;
  19. HBRUSH hBrush;
  20. MSG msg;
  21. LONG l;
  22. LONG lflags;
  23. HWND hbutton;
  24. #ifdef WIN32
  25. HANDLE hmem;
  26. LPCRITICAL_SECTION lpcs;
  27. #endif
  28. switch (message) {
  29. case WM_COMMAND:
  30. #ifdef WIN32
  31. if(LOWORD(wParam)==0 && HIWORD(wParam)==BN_CLICKED)
  32. SendMessage(hwnd,WM_CLOSE,0,0L);
  33. if(LOWORD(wParam)==1 && HIWORD(wParam)==BN_CLICKED) {
  34. hbutton=GetDlgItem(hwnd,1);
  35. lflags=GetWindowLong(hwnd,OFFSET_FLAGS);
  36. if(lflags&FLAG_PAUSE) {
  37. SetFlag(hwnd,FLAG_PAUSE,OFF);
  38. SetWindowText(hbutton,"Pause");
  39. CheckDlgButton(hwnd,1,0);
  40. SetFocus(hwnd);
  41. UpdateWindow(hbutton);
  42. TimerFunc(hwndMain,WM_TIMER,1,0);
  43. }
  44. else {
  45. SetFlag(hwnd,FLAG_PAUSE,ON);
  46. SetWindowText(hbutton,"Start");
  47. CheckDlgButton(hwnd,1,0);
  48. SetFocus(hwnd);
  49. InvalidateRect(hbutton,NULL,FALSE);
  50. UpdateWindow(hbutton);
  51. }
  52. }
  53. #else
  54. if(wParam==1 && HIWORD(lParam)==BN_CLICKED) {
  55. hbutton=GetDlgItem(hwnd,1);
  56. lflags=GetWindowLong(hwnd,OFFSET_FLAGS);
  57. if(lflags&FLAG_PAUSE) {
  58. SetFlag(hwnd,FLAG_PAUSE,OFF);
  59. SetWindowText(GetDlgItem(hwnd,1),"Pause");
  60. TimerFunc(hwndMain,WM_TIMER,1,0);
  61. CheckDlgButton(hwnd,1,0);
  62. SetFocus(hwnd);
  63. InvalidateRect(hbutton,NULL,FALSE);
  64. UpdateWindow(hbutton);
  65. }
  66. else {
  67. SetFlag(hwnd,FLAG_PAUSE,ON);
  68. SetWindowText(GetDlgItem(hwnd,1),"Start");
  69. CheckDlgButton(hwnd,1,0);
  70. SetFocus(hwnd);
  71. InvalidateRect(hbutton,NULL,FALSE);
  72. UpdateWindow(hbutton);
  73. }
  74. }
  75. if(wParam==0 && HIWORD(lParam)==BN_CLICKED)
  76. SendMessage(hwnd,WM_CLOSE,0,0L);
  77. #endif
  78. break;
  79. case WM_ENDSESSION:
  80. case WM_CLOSE:
  81. // Shutdown timers
  82. if (fClient)
  83. {
  84. CloseClient();
  85. }
  86. else {
  87. KillTimer(hwndMain,(UINT)GetThreadLong(GETCURRENTTHREADID(),OFFSET_SERVERTIMER));
  88. }
  89. l=GetWindowLong(hwndMain,OFFSET_FLAGS);
  90. #ifdef WIN32
  91. if(l&FLAG_MULTTHREAD) {
  92. // Start conversations disconnecting.
  93. ThreadDisconnect();
  94. // Start child thread exit
  95. ThreadShutdown();
  96. }
  97. #endif
  98. // This will stop us using hwndDisplay and hwndMain
  99. // after there destroyed.
  100. SetFlag(hwnd,FLAG_STOP,ON);
  101. UninitializeDDE();
  102. // Free memory allocated for Net address.
  103. if(l&FLAG_NET) {
  104. if(hmemNet) FreeMem(hmemNet);
  105. hmemNet=0;
  106. }
  107. // Clean out message queue (main thread)
  108. while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
  109. if(msg.message!=WM_TIMER) {
  110. TranslateMessage (&msg);
  111. DispatchMessage (&msg);
  112. }
  113. }
  114. #ifdef WIN32
  115. // Can Not rely on the critical section for our flag update
  116. // after this point.
  117. SetFlag(hwnd,FLAG_SYNCPAINT,OFF);
  118. // OK, Shutdown is now under way. We need to wait until
  119. // all child threads exit before removing our critical section
  120. // and completing shutdown for main thread.
  121. if(l&FLAG_MULTTHREAD) {
  122. ThreadWait(hwndMain);
  123. hmem=(HANDLE)GetWindowLong(hwndMain,OFFSET_CRITICALSECT);
  124. SetWindowLong(hwndMain,OFFSET_CRITICALSECT,0L);
  125. if(hmem)
  126. {
  127. lpcs=GlobalLock(hmem);
  128. if(lpcs) DeleteCriticalSection(lpcs);
  129. GlobalUnlock(hmem);
  130. GlobalFree(hmem);
  131. }
  132. }
  133. #endif
  134. FreeThreadInfo(GETCURRENTTHREADID());
  135. // Say goodbye to main window. Child threads must be finished
  136. // before making this call.
  137. DestroyWindow(hwnd);
  138. break;
  139. case WM_DESTROY:
  140. PostQuitMessage(0);
  141. break;
  142. case WM_ERASEBKGND:
  143. return 1;
  144. case WM_PAINT:
  145. BeginPaint(hwnd, &ps);
  146. hBrush=CreateSolidBrush(WHITE);
  147. FillRect(ps.hdc,&ps.rcPaint,hBrush);
  148. DeleteObject(hBrush);
  149. PaintTest(hwnd,&ps);
  150. EndPaint(hwnd, &ps);
  151. break;
  152. default:
  153. return(DefWindowProc(hwnd, message, wParam, lParam));
  154. }
  155. return(0L);
  156. }
  157. #ifdef WIN32
  158. BOOL ThreadShutdown( VOID ) {
  159. INT i,nCount,nId,nOffset;
  160. nCount=GetWindowLong(hwndMain,OFFSET_THRDCOUNT);
  161. nOffset=OFFSET_THRD2ID;
  162. for(i=0;i<nCount-1;i++) {
  163. nId=GetWindowLong(hwndMain,nOffset);
  164. if(!PostThreadMessage(nId,EXIT_THREAD,0,0L))
  165. {
  166. Sleep(200);
  167. if(!PostThreadMessage(nId,EXIT_THREAD,0,0L)) {
  168. DOut(hwndMain,"DdeStrs.Exe -- ERR:PostThreadMessage failed 4 EXIT_THREAD\r\n",NULL,0);
  169. }
  170. }
  171. nOffset=nOffset+4;
  172. }
  173. return TRUE;
  174. }
  175. BOOL ThreadDisconnect( VOID ) {
  176. INT i,nCount,nId,nOffset;
  177. nCount=GetWindowLong(hwndMain,OFFSET_THRDCOUNT);
  178. nOffset=OFFSET_THRD2ID;
  179. for(i=0;i<nCount-1;i++) {
  180. nId=GetWindowLong(hwndMain,nOffset);
  181. if(!PostThreadMessage(nId,START_DISCONNECT,0,0L))
  182. {
  183. Sleep(200);
  184. if(!PostThreadMessage(nId,START_DISCONNECT,0,0L)) {
  185. DOut(hwndMain,"DdeStrs.Exe -- ERR:PostThreadMessage failed 4 START_DISCONNECT\r\n",NULL,0);
  186. }
  187. }
  188. nOffset=nOffset+4;
  189. }
  190. return TRUE;
  191. }
  192. #endif
  193. VOID PaintTest(
  194. HWND hwnd,
  195. PAINTSTRUCT *pps)
  196. {
  197. RECT rc,r;
  198. static CHAR szT[40];
  199. LONG cClienthConvs,cServerhConvs;
  200. GetClientRect(hwnd, &rc);
  201. OffsetRect(&rc, 0, cyText);
  202. rc.bottom = rc.top + cyText;
  203. #ifdef WIN16
  204. // Test Mode
  205. if(IntersectRect(&r,&(pps->rcPaint),&rc)) {
  206. if(fServer && fClient)
  207. {
  208. DrawText(pps->hdc, "Client/Server (w16)", -1, &rc, DT_LEFT);
  209. }
  210. else {
  211. if(fServer)
  212. {
  213. DrawText(pps->hdc, "Server (w16)", -1, &rc, DT_LEFT);
  214. }
  215. else {
  216. DrawText(pps->hdc, "Client (w16)", -1, &rc, DT_LEFT);
  217. }
  218. }
  219. }
  220. OffsetRect(&rc, 0, 2*cyText); // Skip a line before next item
  221. #else
  222. // Test Mode
  223. if(IntersectRect(&r,&(pps->rcPaint),&rc)) {
  224. if(fServer && fClient)
  225. {
  226. DrawText(pps->hdc, "Client/Server (w32)", -1, &rc, DT_LEFT);
  227. }
  228. else {
  229. if(fServer)
  230. {
  231. DrawText(pps->hdc, "Server (w32)", -1, &rc, DT_LEFT);
  232. }
  233. else {
  234. DrawText(pps->hdc, "Client (w32)", -1, &rc, DT_LEFT);
  235. }
  236. }
  237. }
  238. OffsetRect(&rc, 0, 2*cyText); // Skip a line before next item
  239. #endif
  240. // Stress Percentage
  241. if(IntersectRect(&r,&(pps->rcPaint),&rc)) {
  242. DrawText(pps->hdc,"Stress %", -1, &rc, DT_LEFT);
  243. #ifdef WIN32
  244. wsprintf(szT, "%d", GetWindowLong(hwndMain,OFFSET_STRESS));
  245. #else
  246. wsprintf(szT, "%ld", GetWindowLong(hwndMain,OFFSET_STRESS));
  247. #endif
  248. CopyRect(&r,&rc);
  249. r.left=cxText*LONGEST_LINE;
  250. DrawText(pps->hdc, szT, -1, &r, DT_LEFT);
  251. }
  252. OffsetRect(&rc, 0, cyText);
  253. // Run Time
  254. if(IntersectRect(&r,&(pps->rcPaint),&rc)) {
  255. DrawText(pps->hdc,"Run Time", -1, &rc, DT_LEFT);
  256. #ifdef WIN32
  257. wsprintf(szT, "%d", GetWindowLong(hwndMain,OFFSET_RUNTIME));
  258. #else
  259. wsprintf(szT, "%ld", GetWindowLong(hwndMain,OFFSET_RUNTIME));
  260. #endif
  261. CopyRect(&r,&rc);
  262. r.left=cxText*LONGEST_LINE;
  263. DrawText(pps->hdc, szT, -1, &r, DT_LEFT);
  264. }
  265. OffsetRect(&rc, 0, cyText);
  266. // Time Elapsed
  267. if(IntersectRect(&r,&(pps->rcPaint),&rc)) {
  268. DrawText(pps->hdc, "Time Elapsed", -1, &rc, DT_LEFT);
  269. #ifdef WIN32
  270. wsprintf(szT, "%d", GetWindowLong(hwndMain,OFFSET_TIME_ELAPSED));
  271. #else
  272. wsprintf(szT, "%ld", GetWindowLong(hwndMain,OFFSET_TIME_ELAPSED));
  273. #endif
  274. CopyRect(&r,&rc);
  275. r.left=cxText*LONGEST_LINE;
  276. DrawText(pps->hdc, szT, -1, &r, DT_LEFT);
  277. }
  278. OffsetRect(&rc, 0, cyText);
  279. // *** Count Client Connections ****
  280. if(IntersectRect(&r,&(pps->rcPaint),&rc)) {
  281. cClienthConvs=GetCurrentCount(hwnd,OFFSET_CCLIENTCONVS);
  282. DrawText(pps->hdc,"Client Connect", -1, &rc, DT_LEFT);
  283. #ifdef WIN32
  284. wsprintf(szT, "%d", cClienthConvs);
  285. #else
  286. wsprintf(szT, "%ld", cClienthConvs);
  287. #endif
  288. CopyRect(&r,&rc);
  289. r.left=cxText*LONGEST_LINE;
  290. DrawText(pps->hdc, szT, -1, &r, DT_LEFT);
  291. } // if IntersectRect
  292. OffsetRect(&rc, 0, cyText);
  293. // *** Server Connections ***
  294. if(IntersectRect(&r,&(pps->rcPaint),&rc)) {
  295. DrawText(pps->hdc,"Server Connect", -1, &rc, DT_LEFT);
  296. cServerhConvs=GetCurrentCount(hwnd,OFFSET_CSERVERCONVS);
  297. #ifdef WIN32
  298. wsprintf(szT, "%d", cServerhConvs );
  299. #else
  300. wsprintf(szT, "%ld", cServerhConvs );
  301. #endif
  302. CopyRect(&r,&rc);
  303. r.left=cxText*LONGEST_LINE;
  304. DrawText(pps->hdc, szT, -1, &r, DT_LEFT);
  305. }
  306. OffsetRect(&rc, 0, cyText);
  307. // Client Count (for checking balence between apps)
  308. if(IntersectRect(&r,&(pps->rcPaint),&rc)) {
  309. DrawText(pps->hdc,"Client Count", -1, &rc, DT_LEFT);
  310. #ifdef WIN32
  311. wsprintf(szT, "%d",GetWindowLong(hwnd,OFFSET_CLIENT));
  312. #else
  313. wsprintf(szT, "%ld",GetWindowLong(hwnd,OFFSET_CLIENT));
  314. #endif
  315. CopyRect(&r,&rc);
  316. r.left=cxText*LONGEST_LINE;
  317. DrawText(pps->hdc, szT, -1, &r, DT_LEFT);
  318. }
  319. OffsetRect(&rc, 0, cyText);
  320. // Server Count (for checking balence between apps)
  321. if(IntersectRect(&r,&(pps->rcPaint),&rc)) {
  322. DrawText(pps->hdc,"Server Count", -1, &rc, DT_LEFT);
  323. #ifdef WIN32
  324. wsprintf(szT, "%d", GetWindowLong(hwnd,OFFSET_SERVER));
  325. #else
  326. wsprintf(szT, "%ld", GetWindowLong(hwnd,OFFSET_SERVER));
  327. #endif
  328. CopyRect(&r,&rc);
  329. r.left=cxText*LONGEST_LINE;
  330. DrawText(pps->hdc, szT, -1, &r, DT_LEFT);
  331. }
  332. OffsetRect(&rc, 0, cyText);
  333. // Delay
  334. if(IntersectRect(&r,&(pps->rcPaint),&rc)) {
  335. DrawText(pps->hdc,"Delay", -1, &rc, DT_LEFT);
  336. #ifdef WIN32
  337. wsprintf(szT, "%d", GetWindowLong(hwndMain,OFFSET_DELAY));
  338. #else
  339. wsprintf(szT, "%ld", GetWindowLong(hwndMain,OFFSET_DELAY));
  340. #endif
  341. CopyRect(&r,&rc);
  342. r.left=cxText*LONGEST_LINE;
  343. DrawText(pps->hdc, szT, -1, &r, DT_LEFT);
  344. }
  345. OffsetRect(&rc, 0, cyText);
  346. }
  347. int PASCAL WinMain(
  348. HINSTANCE hInstance,
  349. HINSTANCE hPrev,
  350. LPSTR lpszCmdLine,
  351. int cmdShow)
  352. {
  353. MSG msg;
  354. HDC hdc;
  355. WNDCLASS wc;
  356. TEXTMETRIC tm;
  357. INT x,y,cx,cy;
  358. #ifdef WIN32
  359. LONG lflags;
  360. #endif
  361. DWORD idI;
  362. HWND hwndDisplay;
  363. INT nThrd;
  364. CHAR sz[250];
  365. CHAR sz2[250];
  366. LPSTR lpszOut=&sz[0];
  367. LPSTR lpsz=&sz2[0];
  368. #ifdef WIN32
  369. DWORD dwer;
  370. #endif
  371. hInst=hInstance;
  372. if(!SetMessageQueue(100)) {
  373. MessageBox(NULL,"SetMessageQueue failed. Test aborting.","Error:DdeStrs",MB_ICONSTOP|MB_OK);
  374. return FALSE;
  375. }
  376. wc.style = 0;
  377. wc.lpfnWndProc = MainWndProc;
  378. wc.cbClsExtra = 0;
  379. wc.cbWndExtra = WND;
  380. wc.hInstance = hInst;
  381. wc.hIcon = LoadIcon(hInst,MAKEINTRESOURCE(IDR_ICON));
  382. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  383. wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE+1);
  384. wc.lpszMenuName = NULL;
  385. wc.lpszClassName = szClass;
  386. if(!hPrev) {
  387. if (!RegisterClass(&wc) )
  388. {
  389. #if 0
  390. // This was removed because the system was running out of resources (ALPHA only)
  391. // which caused this occasionaly to fail. Rather than continue to bring
  392. // the message box up (for a known stress situation) the test will abort
  393. // and try again.
  394. MessageBox(NULL,"RegisterClass failed. Test aborting.","Error:DdeStrs",MB_ICONSTOP|MB_OK);
  395. #endif
  396. return FALSE;
  397. }
  398. }
  399. hwndMain = CreateWindowEx( WS_EX_DLGMODALFRAME,
  400. szClass,
  401. szClass,
  402. WS_OVERLAPPED|WS_MINIMIZEBOX|WS_CLIPCHILDREN,
  403. 0,
  404. 0,
  405. 0,
  406. 0,
  407. NULL,
  408. NULL,
  409. hInst,
  410. NULL);
  411. #ifdef WIN32
  412. dwer=GetLastError(); // We want LastError Associated with CW call
  413. #endif
  414. if (!hwndMain) {
  415. MessageBox(NULL,"Could Not Create Main Window. Test aborting.","Error:DdeStrs",MB_ICONSTOP|MB_OK);
  416. UnregisterClass(szClass,hInst);
  417. return FALSE;
  418. }
  419. #ifdef WIN32
  420. if (!IsWindow(hwndMain)) {
  421. TStrCpy(lpsz,"CreateWindowEx failed for Main Window but did not return NULL! Test aborting. HWND=%u, LastEr=%u");
  422. wsprintf(lpszOut,lpsz,hwndMain,dwer);
  423. MessageBox(NULL,lpszOut,"Error:DdeStrs",MB_ICONSTOP|MB_OK);
  424. UnregisterClass(szClass,hInst);
  425. return FALSE;
  426. }
  427. #else
  428. if (!IsWindow(hwndMain)) {
  429. TStrCpy(lpsz,"CreateWindowEx failed for Main Window but did not return NULL! Test aborting. HWND=%u");
  430. wsprintf(lpszOut,lpsz,hwndMain);
  431. MessageBox(NULL,lpszOut,"Error:DdeStrs",MB_ICONSTOP|MB_OK);
  432. UnregisterClass(szClass,hInst);
  433. return FALSE;
  434. }
  435. #endif
  436. if (!ParseCommandLine(hwndMain,lpszCmdLine)) {
  437. DestroyWindow(hwndMain);
  438. UnregisterClass(szClass,hInst);
  439. return FALSE;
  440. }
  441. // Note: This needs to be there even for win 16 execution. The
  442. // name may be confusing. for win 16 there is obviously only
  443. // a single thread. This is handled by the call.
  444. nThrd=GetWindowLong(hwndMain,OFFSET_THRDCOUNT);
  445. // Currently ddestrs has a hardcoded thread limit (at THREADLIMIT). So
  446. // this should NEVER be less than one or greater than THREADLIMIT.
  447. #ifdef WIN32
  448. if(nThrd<1 || nThrd>THREADLIMIT) {
  449. BOOL fVal;
  450. dwer=GetLastError();
  451. if(IsWindow(hwndMain)) fVal=TRUE;
  452. else fVal=FALSE;
  453. TStrCpy(lpsz,"GetWindowLong failed querying thread count!. Test aborting... INFO:hwnd=%u, LastEr=%u, Is hwnd valid=%u, nThrd=%u");
  454. wsprintf(lpszOut,lpsz,hwndMain,dwer,fVal,nThrd);
  455. MessageBox(NULL,lpszOut,"Error:DdeStrs",MB_ICONSTOP|MB_OK);
  456. DestroyWindow(hwndMain);
  457. UnregisterClass(szClass,hInst);
  458. return FALSE;
  459. }
  460. #endif
  461. if(!CreateThreadExtraMem( EXTRA_THREAD_MEM,nThrd)) {
  462. MessageBox(NULL,"Could Not Alocate Get/SetThreadLong(). Test aborting.","Error:DdeStrs",MB_ICONSTOP|MB_OK);
  463. DestroyWindow(hwndMain);
  464. UnregisterClass(szClass,hInst);
  465. return FALSE;
  466. }
  467. // We always need the thread id for the main thread. (for use
  468. // in Get/SetThreadLong(). Other thread id's are initialized in
  469. // ThreadInit().
  470. SetWindowLong(hwndMain,OFFSET_THRDMID,GETCURRENTTHREADID());
  471. if(!InitThreadInfo(GETCURRENTTHREADID())) {
  472. MessageBox(NULL,"Could Not Alocate Thread Local Storage. Test aborting.","Error:DdeStrs",MB_ICONSTOP|MB_OK);
  473. DestroyWindow(hwndMain);
  474. UnregisterClass(szClass,hInst);
  475. return FALSE;
  476. }
  477. hdc = GetDC(hwndMain);
  478. GetTextMetrics(hdc, &tm);
  479. cyText = tm.tmHeight;
  480. cxText = tm.tmAveCharWidth;
  481. // We need to add in extra area for each additional DisplayWindow
  482. // used for each addtional thread.
  483. nThrd=(INT)GetWindowLong(hwndMain,OFFSET_THRDCOUNT);
  484. cy = tm.tmHeight*NUM_ROWS+((nThrd-1)*(3*cyText));
  485. cx = tm.tmAveCharWidth*NUM_COLUMNS;
  486. ReleaseDC(hwndMain,hdc);
  487. // Old ways of positioning.
  488. // y=DIV((GetSystemMetrics(SM_CYSCREEN)-cy),3)*2;
  489. // y=(DIV(GetSystemMetrics(SM_CYSCREEN),10)*3);
  490. // Position as if 5 threads with bottom of window at bottom of
  491. // screen.
  492. y=GetSystemMetrics(SM_CYSCREEN)-(tm.tmHeight*NUM_ROWS+(12*cyText));
  493. x=GetSystemMetrics(SM_CXSCREEN);
  494. if(fServer && fClient) {
  495. x=x-(cx*3); // Init for standard values.
  496. }
  497. else {
  498. if(fServer)
  499. {
  500. x=x-cx;
  501. }
  502. else {
  503. x=x-(cx*2);
  504. }
  505. }
  506. SetWindowPos( hwndMain,
  507. NULL,
  508. x,
  509. y,
  510. cx,
  511. cy,
  512. SWP_NOZORDER|SWP_NOACTIVATE );
  513. ShowWindow (hwndMain, cmdShow);
  514. CreateButton(hwndMain);
  515. UpdateWindow (hwndMain);
  516. #ifdef WIN32
  517. SetFlag(hwndMain,FLAG_SYNCPAINT,ON);
  518. lflags=GetWindowLong(hwndMain,OFFSET_FLAGS);
  519. if(lflags&FLAG_MULTTHREAD) { // CreateThreads
  520. if(!ThreadInit(hwndMain)) {
  521. DestroyWindow(hwndMain);
  522. UnregisterClass(szClass,hInst);
  523. return FALSE;
  524. }
  525. }
  526. #endif
  527. hwndDisplay=CreateDisplayWindow(hwndMain,1);
  528. if(!hwndDisplay) {
  529. MessageBox(NULL,"Could Not Create Test Display Window. Test aborting.","Error:DdeStrs",MB_ICONSTOP|MB_OK);
  530. DestroyWindow(hwndMain);
  531. UnregisterClass(szClass,hInst);
  532. return FALSE;
  533. }
  534. else {
  535. SetThreadLong(GETCURRENTTHREADID(),OFFSET_HWNDDISPLAY,(LONG)hwndDisplay);
  536. }
  537. if (!InitializeDDE((PFNCALLBACK)CustomCallback,
  538. &idI,
  539. ServiceInfoTable,
  540. fServer ?
  541. APPCLASS_STANDARD
  542. :
  543. APPCLASS_STANDARD | APPCMD_CLIENTONLY,
  544. hInst)) {
  545. DDEMLERROR("DdeStrs.Exe -- Error Dde inititialization failed\r\n");
  546. DestroyWindow(hwndMain);
  547. UnregisterClass(szClass,hInst);
  548. return(FALSE);
  549. }
  550. SetThreadLong(GETCURRENTTHREADID(),OFFSET_IDINST,idI);
  551. if (fClient)
  552. {
  553. InitClient();
  554. }
  555. else {
  556. // Only needed if we are not a client. In case of
  557. // client/server only call InitClient() which start
  558. // a timer which can be used for time checks.
  559. SetTimer( hwndMain,
  560. (UINT)GetThreadLong(GETCURRENTTHREADID(),OFFSET_SERVERTIMER),
  561. PNT_INTERVAL,
  562. TimerFunc);
  563. }
  564. while (GetMessage(&msg, NULL, 0, 0)) {
  565. if(IsTimeExpired(hwndMain)) {
  566. // We only want to send a single WM_CLOSE
  567. if(fnoClose) {
  568. fnoClose=FALSE;
  569. PostMessage(hwndMain,WM_CLOSE,0,0L);
  570. }
  571. }
  572. TranslateMessage (&msg);
  573. DispatchMessage (&msg);
  574. }
  575. FreeThreadExtraMem();
  576. return(TRUE);
  577. }
  578. #ifdef WIN32
  579. /************************** Private Function ****************************\
  580. *
  581. * ThreadInit
  582. *
  583. * Create secondary test threads
  584. *
  585. \**************************************************************************/
  586. BOOL ThreadInit( HWND hwnd ) {
  587. LONG l,ll;
  588. PLONG lpIDThread=&ll;
  589. HANDLE hthrd;
  590. INT nOffset,nCount,i,n;
  591. HANDLE hmem;
  592. HANDLE *lph;
  593. char sz[20];
  594. LPSTR lpsz=&sz[0];
  595. nCount=GetWindowLong(hwnd,OFFSET_THRDCOUNT);
  596. nOffset=OFFSET_THRD2;
  597. for(i=1;i<nCount;i++) {
  598. hmem=GetMemHandle(((sizeof(HANDLE)*2)+sizeof(INT)));
  599. lph=(HANDLE *)GlobalLock(hmem);
  600. *lph=hwnd;
  601. *(lph+1)=hmem;
  602. *(lph+2)=(HANDLE)(i+1);
  603. hthrd=CreateThread(NULL,0,SecondaryThreadMain,(LPVOID)lph,0,lpIDThread);
  604. if (!hthrd) {
  605. DOut(hwnd,"DdeStrs.Exe -- ERR:Could not Create Thread #%u\r\n",0,i+1);
  606. GlobalUnlock(hmem);
  607. FreeMemHandle(hmem);
  608. // it's important we turn this flag off since no threads
  609. // where successfully created (cleanup code)
  610. SetFlag(hwnd,FLAG_MULTTHREAD,OFF);
  611. if (i==1) return FALSE;
  612. else {
  613. // Cleanup threads before we abort.
  614. for(n=1;n<i;n++) {
  615. nOffset=OFFSET_THRD2;
  616. TerminateThread((HANDLE)GetWindowLong(hwnd,nOffset),0);
  617. SetWindowLong(hwnd,nOffset,0L);
  618. nOffset=nOffset+4;
  619. } // for
  620. return FALSE;
  621. } // else
  622. } // if
  623. SetWindowLong(hwnd,nOffset+ID_OFFSET,(LONG)(*lpIDThread));
  624. SetWindowLong(hwnd,nOffset,(LONG)hthrd);
  625. nOffset=nOffset+4;
  626. } // for
  627. return TRUE;
  628. } // ThreadInit
  629. /*************************** Private Function ******************************\
  630. SecondaryThreadMain
  631. Effects: Start of execution for second thread. First order of buisness is
  632. create the test window and start queue processing.
  633. Return value:
  634. \***************************************************************************/
  635. DWORD SecondaryThreadMain( DWORD dw )
  636. {
  637. HWND hwndMain;
  638. MSG msg;
  639. HANDLE * lph;
  640. HANDLE hmem;
  641. INT nThrd;
  642. DWORD idI;
  643. HWND hwndDisplay;
  644. LONG nTc;
  645. lph=(HANDLE *)dw;
  646. hwndMain=(HWND)*lph;
  647. hmem =(HANDLE)*(lph+1);
  648. nThrd =(INT)*(lph+2);
  649. GlobalUnlock(hmem);
  650. FreeMemHandle(hmem);
  651. if(!InitThreadInfo(GETCURRENTTHREADID())) {
  652. DDEMLERROR("DdeStrs.Exe -- Error InitThreadInfo failed, Aborting thread\r\n");
  653. nTc=GetWindowLong(hwndMain,OFFSET_THRDCOUNT);
  654. SetWindowLong(hwndMain,OFFSET_THRDCOUNT,(LONG)(nTc-1));
  655. ExitThread(1L);
  656. }
  657. SetThreadLong(GETCURRENTTHREADID(),OFFSET_IDINST,idI);
  658. hwndDisplay=CreateDisplayWindow( hwndMain,
  659. IDtoTHREADNUM(GETCURRENTTHREADID()));
  660. if(!IsWindow(hwndDisplay)) {
  661. DDEMLERROR("DdeStrs.Exe -- ERR:Could not create Display Window, Thread aborting\r\n");
  662. nTc=GetWindowLong(hwndMain,OFFSET_THRDCOUNT);
  663. SetWindowLong(hwndMain,OFFSET_THRDCOUNT,(LONG)(nTc-1));
  664. ExitThread(1L);
  665. return FALSE;
  666. }
  667. else {
  668. SetThreadLong(GETCURRENTTHREADID(),OFFSET_HWNDDISPLAY,hwndDisplay);
  669. }
  670. if (!InitializeDDE((PFNCALLBACK)CustomCallback,
  671. &idI,
  672. ServiceInfoTable,
  673. fServer ?
  674. APPCLASS_STANDARD
  675. :
  676. APPCLASS_STANDARD | APPCMD_CLIENTONLY,
  677. hInst)) {
  678. DDEMLERROR("DdeStrs.Exe -- Error Dde inititialization failed for secondary thread!\r\n");
  679. FreeThreadInfo(GETCURRENTTHREADID());
  680. nTc=GetWindowLong(hwndMain,OFFSET_THRDCOUNT);
  681. SetWindowLong(hwndMain,OFFSET_THRDCOUNT,(LONG)(nTc-1));
  682. ExitThread(1L);
  683. }
  684. if (fClient)
  685. {
  686. InitClient();
  687. }
  688. else {
  689. // Only needed if we are not a client. In case of
  690. // client/server only call InitClient() which start
  691. // a timer which can be used for time checks.
  692. SetTimer( hwndMain,
  693. (UINT)GetThreadLong(GETCURRENTTHREADID(),OFFSET_SERVERTIMER),
  694. PNT_INTERVAL,
  695. TimerFunc);
  696. }
  697. while (GetMessage(&msg,NULL,0,0)) {
  698. if(msg.message==START_DISCONNECT)
  699. {
  700. if (fClient)
  701. {
  702. CloseClient();
  703. }
  704. }
  705. else {
  706. if(msg.message==EXIT_THREAD)
  707. {
  708. PostQuitMessage(1);
  709. }
  710. else {
  711. TranslateMessage(&msg);
  712. DispatchMessage(&msg);
  713. } // EXIT_THREAD
  714. } // START_DISCONNECT
  715. } // while
  716. SetFlag(hwndMain,FLAG_STOP,ON);
  717. // Shutdown timers
  718. if (!fClient)
  719. {
  720. KillTimer(hwndMain,GetThreadLong(GETCURRENTTHREADID(),OFFSET_SERVERTIMER));
  721. }
  722. UninitializeDDE();
  723. FreeThreadInfo(GETCURRENTTHREADID());
  724. // This is to release the semaphore set before completing
  725. // exit on main thread.
  726. switch (nThrd) {
  727. case 2: SetFlag(hwndMain,FLAG_THRD2,ON);
  728. break;
  729. case 3: SetFlag(hwndMain,FLAG_THRD3,ON);
  730. break;
  731. case 4: SetFlag(hwndMain,FLAG_THRD4,ON);
  732. break;
  733. case 5: SetFlag(hwndMain,FLAG_THRD5,ON);
  734. break;
  735. default:
  736. DOut(hwndMain,"DdeStrs.Exe -- ERR: Unexpected switch value in SecondaryThreadMain, value=%u\r\n",0,nThrd);
  737. break;
  738. } // switch
  739. ExitThread(1L);
  740. return 1;
  741. }
  742. #endif
  743. /************************** Public Function *****************************\
  744. *
  745. * InitThrdInfo - This routine allocates memory needed for storage for
  746. * thread local variables. This routine needs to be called
  747. * for each thread.
  748. *
  749. * Note: I am relying on the fact that the call GetMemHandle() calls
  750. * GlobalAlloc() specifying the GMEM_ZEROINIT flag. These value need
  751. * to be zero starting off.
  752. \**************************************************************************/
  753. BOOL InitThreadInfo( DWORD dwid ) {
  754. HANDLE hmem;
  755. INT nThrd;
  756. hmem = GetMemHandle(sizeof(HCONV)*MAX_SERVER_HCONVS);
  757. SetThreadLong(dwid,OFFSET_HSERVERCONVS,(LONG)hmem);
  758. if( hmem==NULL ) {
  759. DOut(hwndMain,"DdeStrs.Exe -- ERR: Could not allocate thread local storage(Server Conversation List)\r\n",0,0);
  760. return FALSE;
  761. }
  762. hmem = GetMemHandle(sizeof(HANDLE)*NUM_FORMATS);
  763. SetThreadLong(dwid,OFFSET_HAPPOWNED,(LONG)hmem);
  764. if( hmem==NULL ) {
  765. DOut(hwndMain,"DdeStrs.Exe -- ERR: Could not allocate thread local storage(AppOwned Flag List)\r\n",0,0);
  766. FreeMemHandle((HANDLE)GetThreadLong(dwid,OFFSET_HSERVERCONVS));
  767. return FALSE;
  768. }
  769. nThrd=IDtoTHREADNUM(dwid);
  770. SetThreadLong(dwid,OFFSET_SERVERTIMER,nThrd*2);
  771. SetThreadLong(dwid,OFFSET_CLIENTTIMER,(nThrd*2)+1);
  772. return TRUE;
  773. }
  774. #ifdef WIN32
  775. /************************** Private Function ****************************\
  776. *
  777. * IDtoTHREADNUM - Find out current thread.
  778. *
  779. \**************************************************************************/
  780. INT IDtoTHREADNUM( DWORD dwid ) {
  781. INT nWndOff,nThrd,nThrdCount,n;
  782. nWndOff=OFFSET_THRDMID;
  783. nThrdCount=GetWindowLong(hwndMain,OFFSET_THRDCOUNT);
  784. n=nThrdCount;
  785. nThrd=1;
  786. while( n>0 ) {
  787. if(dwid==(DWORD)GetWindowLong(hwndMain,nWndOff))
  788. {
  789. n=-1; // Exit loop
  790. } // if
  791. else {
  792. nWndOff=nWndOff+4;
  793. nThrd++;
  794. n--;
  795. }
  796. } // while
  797. if(nThrd>nThrdCount) {
  798. DDEMLERROR("DdeStrs.Exe -- ERR:Thread Count exceeded!!! in IDtoTHREADNUM()\r\n");
  799. nThrd=nThrdCount;
  800. }
  801. return nThrd;
  802. }
  803. #else
  804. /************************** Private Function ****************************\
  805. *
  806. * IDtoTHREADNUM - Find out current thread.
  807. *
  808. \**************************************************************************/
  809. INT IDtoTHREADNUM( DWORD dwid ) {
  810. return 1;
  811. }
  812. #endif
  813. /************************** Public Function *****************************\
  814. *
  815. * FreeThreadInfo - Free thread information memory.
  816. *
  817. \**************************************************************************/
  818. BOOL FreeThreadInfo( DWORD dwid ) {
  819. HANDLE hmem;
  820. hmem=(HANDLE)GetThreadLong(dwid,OFFSET_HSERVERCONVS);
  821. FreeMemHandle(hmem);
  822. return TRUE;
  823. }
  824. #ifdef WIN32
  825. /************************** Public Function *****************************\
  826. *
  827. * ThreadWait - This routine waits while processing messages until the
  828. * other threads signal they've completed work that must
  829. * be finished before preceeding.
  830. *
  831. \**************************************************************************/
  832. VOID ThreadWait( HWND hwnd ) {
  833. LONG lflags;
  834. INT nCount,nWait;
  835. MSG msg;
  836. lflags=GetWindowLong(hwnd,OFFSET_FLAGS);
  837. nCount=GetWindowLong(hwnd,OFFSET_THRDCOUNT);
  838. nWait=nCount-1;
  839. if(lflags&FLAG_THRD2) nWait-=1;
  840. if(lflags&FLAG_THRD3) nWait-=1;
  841. if(lflags&FLAG_THRD4) nWait-=1;
  842. if(lflags&FLAG_THRD5) nWait-=1;
  843. while (nWait>0) {
  844. while(PeekMessage(&msg,NULL,0,WM_USER-1,PM_REMOVE)) {
  845. TranslateMessage(&msg);
  846. DispatchMessage(&msg);
  847. } // while peekmessage
  848. nWait=nCount-1;
  849. lflags=GetWindowLong(hwnd,OFFSET_FLAGS);
  850. if(lflags&FLAG_THRD2) nWait-=1;
  851. if(lflags&FLAG_THRD3) nWait-=1;
  852. if(lflags&FLAG_THRD4) nWait-=1;
  853. if(lflags&FLAG_THRD5) nWait-=1;
  854. } // while nWait
  855. // Reset for next wait
  856. SetFlag(hwnd,(FLAG_THRD5|FLAG_THRD4|FLAG_THRD3|FLAG_THRD2),OFF);
  857. }
  858. #endif // WIN32
  859. /************************** Private Function ****************************\
  860. *
  861. * SetCount
  862. *
  863. * This routine updates the count under semaphore protection. Not needed for
  864. * one thread, but a must for multithread execution.
  865. *
  866. \**************************************************************************/
  867. LONG SetCount( HWND hwnd, INT nOffset, LONG l, INT ntype ) {
  868. LONG ll;
  869. #if 0
  870. LONG lflags;
  871. #endif
  872. #ifdef WIN32
  873. LPCRITICAL_SECTION lpcs;
  874. HANDLE hmem;
  875. BOOL f=FALSE;
  876. #endif
  877. #if 0
  878. lflags=GetWindowLong(hwnd,OFFSET_FLAGS);
  879. if(ll&FLAG_MULTTHREAD) {
  880. f=TRUE;
  881. hmem=(HANDLE)GetWindowLong(hwnd,OFFSET_CRITICALSECT);
  882. // If we have a valid handle then enter critical section. If
  883. // the handle is still null proceed without a critical section.
  884. // The first calls to this routine are used to setup the
  885. // critical section so we do expect those first calls (while
  886. // we are still sencronized ) for the hmem to be null.
  887. if(hmem) {
  888. lpcs=GlobalLock(hmem);
  889. EnterCriticalSection(lpcs);
  890. }
  891. }
  892. #endif
  893. // This second GetWindowLong call is needed in the critical
  894. // section. The test relies very hevily on the flags and
  895. // it's important to be accurate.
  896. ll=GetWindowLong(hwnd,nOffset);
  897. if(ntype==INC) l=SetWindowLong(hwnd,nOffset,ll+l);
  898. else l=SetWindowLong(hwnd,nOffset,ll-l);
  899. #if 0
  900. if(f) {
  901. if(hmem) {
  902. LeaveCriticalSection(lpcs);
  903. GlobalUnlock(hmem);
  904. }
  905. }
  906. #endif
  907. return l;
  908. }
  909. /************************** Private Function ****************************\
  910. *
  911. * SetFlag
  912. *
  913. * This routine sets a flag under semaphore protection. Not needed for
  914. * one thread, but a must for multithread execution.
  915. *
  916. \**************************************************************************/
  917. LONG SetFlag( HWND hwnd, LONG l, INT ntype ) {
  918. LONG lflags;
  919. #ifdef WIN32
  920. BOOL fCriticalSect=TRUE;
  921. LPCRITICAL_SECTION lpcs;
  922. HANDLE hmem;
  923. BOOL f=FALSE;
  924. #endif
  925. #ifdef WIN32
  926. lflags=GetWindowLong(hwnd,OFFSET_FLAGS);
  927. if(lflags&FLAG_MULTTHREAD &&
  928. lflags&FLAG_SYNCPAINT) {
  929. f=TRUE;
  930. hmem=(HANDLE)GetWindowLong(hwnd,OFFSET_CRITICALSECT);
  931. if(hmem) {
  932. lpcs=GlobalLock(hmem);
  933. EnterCriticalSection(lpcs);
  934. }
  935. else {
  936. fCriticalSect=FALSE;
  937. }
  938. }
  939. #endif
  940. // This second GetWindowLong call is needed in the critical
  941. // section. The test relies very hevily on the flags and
  942. // it's important to be accurate.
  943. lflags=GetWindowLong(hwnd,OFFSET_FLAGS);
  944. if(ntype==ON) l=SetWindowLong(hwnd,OFFSET_FLAGS,FLAGON(lflags,l));
  945. else l=SetWindowLong(hwnd,OFFSET_FLAGS,FLAGOFF(lflags,l));
  946. #ifdef WIN32
  947. if(f) {
  948. if(fCriticalSect) {
  949. LeaveCriticalSection(lpcs);
  950. GlobalUnlock(hmem);
  951. }
  952. }
  953. #endif
  954. return l;
  955. }
  956. /******************************************************************\
  957. * DIV
  958. * 05/06/91
  959. *
  960. * Performs integer division (format x/y) where DIV(x,y)
  961. * Works for negative numbers and y==0;
  962. *
  963. \******************************************************************/
  964. INT DIV( INT x, INT y)
  965. {
  966. INT i=0;
  967. BOOL fNgOn=FALSE;
  968. if (!y) return 0; // if div by 0 retrun error.
  969. if (x<0 && y>0) fNgOn=TRUE; // keep tabs for negitive numbers
  970. if (x>0 && y<0) fNgOn=TRUE;
  971. if (x<0) x=x*-1;
  972. if (y<0) y=y*-1;
  973. x=x-y;
  974. while (x>=0) { // count
  975. x=x-y;
  976. i++;
  977. }
  978. if (fNgOn) i=i*(-1); // should result be negative
  979. return( i );
  980. }
  981. /*************************** Private Function ******************************\
  982. *
  983. * CreateButton
  984. *
  985. \***************************************************************************/
  986. HWND CreateButton( HWND hwnd ) {
  987. RECT r;
  988. HWND hwndB;
  989. HWND hwndP;
  990. INT iButWidth;
  991. LONG lflags;
  992. GetClientRect(hwnd,&r);
  993. lflags=GetWindowLong(hwnd,OFFSET_FLAGS);
  994. if(lflags&FLAG_PAUSE_BUTTON) {
  995. iButWidth=DIV(r.right-r.left,2);
  996. hwndP=CreateWindow("button",
  997. "Start",
  998. BS_PUSHBUTTON|WS_VISIBLE|WS_CHILD|WS_CLIPSIBLINGS,
  999. iButWidth,
  1000. 0,
  1001. r.right-iButWidth,
  1002. cyText,
  1003. hwnd,
  1004. 1,
  1005. GetHINSTANCE(hwnd),
  1006. 0L);
  1007. if (!hwndP) {
  1008. DDEMLERROR("DdeStrs.Exe -- ERR:Failed to create exit button: Continuing...\r\n");
  1009. SetFlag(hwnd,FLAG_PAUSE_BUTTON,OFF);
  1010. iButWidth=r.right-r.left;
  1011. }
  1012. hwndB=CreateWindow("button",
  1013. "Exit",
  1014. BS_PUSHBUTTON|WS_VISIBLE|WS_CHILD|WS_CLIPSIBLINGS,
  1015. 0,
  1016. 0,
  1017. iButWidth,
  1018. cyText,
  1019. hwnd,
  1020. 0,
  1021. GetHINSTANCE(hwnd),
  1022. 0L);
  1023. }
  1024. else {
  1025. hwndB=CreateWindow("button",
  1026. "Exit",
  1027. BS_PUSHBUTTON|WS_VISIBLE|WS_CHILD|WS_CLIPSIBLINGS,
  1028. 0,
  1029. 0,
  1030. r.right-r.left,
  1031. cyText,
  1032. hwnd,
  1033. 0,
  1034. GetHINSTANCE(hwnd),
  1035. 0L);
  1036. }
  1037. if (!hwndB) {
  1038. DDEMLERROR("DdeStrs.Exe -- ERR:Failed to create exit button: Continuing...\r\n");
  1039. }
  1040. return hwndB;
  1041. }
  1042. /***************************************************************************\
  1043. *
  1044. * UpdClient
  1045. *
  1046. * The purpose of this routine update only the area invalidated
  1047. * by the test statistics update. If an error occurs in the area
  1048. * calcualation then update the whole client areaa.
  1049. *
  1050. \***************************************************************************/
  1051. BOOL UpdClient( HWND hwnd, INT iOffset ) {
  1052. RECT r;
  1053. INT iCH,iCW,nThrd;
  1054. #ifdef WIN32
  1055. DWORD dw;
  1056. #endif
  1057. // This call aquires the r.right value.
  1058. GetClientRect(hwnd,&r);
  1059. // We need text information for the monitor being used. This
  1060. // was initialized in CreateFrame.
  1061. iCH=cyText;
  1062. iCW=cxText;
  1063. // Do a quick check, if either of these values are NULL then
  1064. // update the whole client area. This is slower and less
  1065. // elegant but will work in the case of an error.
  1066. if((!iCH) || (!iCW))
  1067. InvalidateRect(hwnd,NULL,TRUE);
  1068. else {
  1069. // Next Calculate r.top and r.bottom
  1070. switch(iOffset) {
  1071. case ALL: // Update all values.
  1072. break;
  1073. case OFFSET_STRESS:
  1074. r.bottom =iCH*4;
  1075. r.top =iCH*3;
  1076. break;
  1077. case OFFSET_RUNTIME:
  1078. r.bottom =iCH*5;
  1079. r.top =iCH*4;
  1080. break;
  1081. case OFFSET_TIME_ELAPSED:
  1082. r.bottom =iCH*6;
  1083. r.top =iCH*5;
  1084. break;
  1085. case OFFSET_CLIENT_CONNECT:
  1086. r.bottom =iCH*7;
  1087. r.top =iCH*6;
  1088. break;
  1089. case OFFSET_SERVER_CONNECT:
  1090. r.bottom =iCH*8;
  1091. r.top =iCH*7;
  1092. break;
  1093. case OFFSET_CLIENT:
  1094. nThrd=(INT)GetWindowLong(hwnd,OFFSET_THRDCOUNT);
  1095. if((GetWindowLong(hwnd,OFFSET_CLIENT)%(NUM_FORMATS*nThrd))==0)
  1096. {
  1097. r.bottom =iCH*9;
  1098. r.top =iCH*8;
  1099. }
  1100. else return TRUE;
  1101. break;
  1102. case OFFSET_SERVER:
  1103. nThrd=(INT)GetWindowLong(hwnd,OFFSET_THRDCOUNT);
  1104. if((GetWindowLong(hwnd,OFFSET_SERVER)%(NUM_FORMATS*nThrd))==0)
  1105. {
  1106. r.bottom =iCH*10;
  1107. r.top =iCH*9;
  1108. }
  1109. else return TRUE;
  1110. break;
  1111. case OFFSET_DELAY:
  1112. r.bottom =iCH*11;
  1113. r.top =iCH*10;
  1114. break;
  1115. default:
  1116. break;
  1117. } // switch
  1118. // Last we set the r.left and the update rect is complete
  1119. if(iOffset!=OFFSET_FLAGS)
  1120. r.left = iCW*LONGEST_LINE;
  1121. InvalidateRect(hwnd,&r,TRUE);
  1122. } // else
  1123. #ifdef WIN16
  1124. UpdateWindow(hwnd);
  1125. #else
  1126. SendMessageTimeout(hwnd,WM_PAINT,0,0L,SMTO_NORMAL,500,&dw);
  1127. #endif
  1128. return TRUE;
  1129. } // UpdClient
  1130. /***************************************************************************\
  1131. *
  1132. * GetCurrentCount
  1133. *
  1134. \***************************************************************************/
  1135. LONG GetCurrentCount( HWND hwnd, INT nOffset ) {
  1136. LONG cClienthConvs =0L;
  1137. INT nThrd,i;
  1138. DWORD dwid;
  1139. nThrd=(INT)GetWindowLong(hwnd,OFFSET_THRDCOUNT);
  1140. for(i=0;i<nThrd;i++) {
  1141. dwid=(DWORD)GetWindowLong(hwnd,OFFSET_THRDMID+(i*4));
  1142. if(nOffset==OFFSET_CCLIENTCONVS)
  1143. cClienthConvs=cClienthConvs+(INT)GetThreadLong(dwid,OFFSET_CCLIENTCONVS);
  1144. else cClienthConvs=cClienthConvs+(INT)GetThreadLong(dwid,OFFSET_CSERVERCONVS);
  1145. } // for i
  1146. return cClienthConvs;
  1147. }
  1148. /***************************************************************************\
  1149. *
  1150. * UpdateCount
  1151. *
  1152. \***************************************************************************/
  1153. BOOL UpdateCount( HWND hwnd, INT iOffset, INT i) {
  1154. LONG ll;
  1155. if(iOffset!=ALL) {
  1156. ll=GetWindowLong(hwnd,iOffset);
  1157. switch(i) {
  1158. case INC: SetCount(hwnd,iOffset,1,INC);
  1159. break;
  1160. case DEC: SetCount(hwnd,iOffset,1,DEC);
  1161. break;
  1162. case STP: SetFlag(hwnd,FLAG_STOP,ON);
  1163. break;
  1164. case PNT: // Paint only!
  1165. break;
  1166. default:
  1167. DDEMLERROR("DdeStrs.Exe - UpdateCount - Unexpected value");
  1168. break;
  1169. } // switch
  1170. } // if
  1171. UpdClient(hwnd,iOffset);
  1172. return TRUE;
  1173. }
  1174. /*****************************************************************************\
  1175. | DOUT
  1176. |
  1177. | created: 29-Jul-91
  1178. | history: 03-Aug-91 <johnsp> created.
  1179. |
  1180. \*****************************************************************************/
  1181. BOOL DOut( HWND hwnd, LPSTR lpsz, LPSTR lpszi, INT i ) {
  1182. char sz[MAX_TITLE_LENGTH];
  1183. LPSTR lpszOut=&sz[0];
  1184. LONG lflags;
  1185. #ifdef WIN32
  1186. LPCRITICAL_SECTION lpcs;
  1187. HANDLE hmem;
  1188. DWORD dwer=0L;
  1189. BOOL fCriticalSect=TRUE;
  1190. BOOL f=FALSE;
  1191. if(!hwnd) hwnd=hwndMain;
  1192. lflags=GetWindowLong(hwnd,OFFSET_FLAGS);
  1193. // FLAG_SYNCPAINT implies FLAG_MULTTHREAD with the addition that
  1194. // we have allocated needed resources to start using the
  1195. // critical section code.
  1196. if(lflags&FLAG_SYNCPAINT) {
  1197. f=TRUE;
  1198. hmem=(HANDLE)GetWindowLong(hwnd,OFFSET_CRITICALSECT);
  1199. if(hmem) {
  1200. lpcs=GlobalLock(hmem);
  1201. EnterCriticalSection(lpcs);
  1202. }
  1203. else {
  1204. fCriticalSect=FALSE;
  1205. }
  1206. }
  1207. #endif
  1208. if (lflags&FLAG_DEBUG) {
  1209. if (lpszi) wsprintf(lpszOut,lpsz,lpszi);
  1210. else wsprintf(lpszOut,lpsz,i);
  1211. OutputDebugString(lpszOut);
  1212. #ifdef WIN32
  1213. dwer=GetLastError();
  1214. wsprintf(lpszOut,"DdeStrs.Exe -- ERR:Val from GetLastError()=%u\n\r",dwer);
  1215. OutputDebugString(lpszOut);
  1216. #endif
  1217. } // if FLAG_DEBUG
  1218. #ifdef WIN32
  1219. // FLAG_SYNCPAINT implies FLAG_MULTTHREAD with the addition that
  1220. // we have allocated needed resources to start using the
  1221. // critical section code.
  1222. if(f) {
  1223. if(fCriticalSect) {
  1224. LeaveCriticalSection(lpcs);
  1225. GlobalUnlock(hmem);
  1226. }
  1227. }
  1228. #endif
  1229. return TRUE;
  1230. }
  1231. /*****************************************************************************\
  1232. | EOUT
  1233. |
  1234. | created: 19-Aug-92
  1235. | history: 19-Aug-92 <johnsp> created.
  1236. |
  1237. \*****************************************************************************/
  1238. BOOL EOut( LPSTR lpsz ) {
  1239. DOut((HWND)NULL,lpsz,(LPSTR)NULL,0);
  1240. return TRUE;
  1241. }
  1242. /*************************** Private Function ******************************\
  1243. GetMemHandle
  1244. \***************************************************************************/
  1245. HANDLE GetMemHandle( INT ic ) {
  1246. HANDLE hmem;
  1247. hmem=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,ic);
  1248. if(hmem) {
  1249. SetCount(hwndMain,OFFSET_MEM_ALLOCATED,GlobalSize(hmem),INC);
  1250. }
  1251. else {
  1252. DOut(hwndMain,"DdeStrs.Exe -- ERR:GlobalAlloc ret=%u\n\r",0,0);
  1253. }
  1254. return hmem;
  1255. }
  1256. /*************************** Private Function ******************************\
  1257. GetMem
  1258. \***************************************************************************/
  1259. LPSTR GetMem( INT ic, LPHANDLE lphmem) {
  1260. LPSTR lpsz;
  1261. *lphmem=GetMemHandle(ic);
  1262. lpsz=GlobalLock(*lphmem);
  1263. if(!lpsz) {
  1264. DOut(hwndMain,"DdeStrs.Exe -- ERR:GlobalLock ret=%u (not locked)\n\r",0,0);
  1265. FreeMemHandle(*lphmem);
  1266. return NULL;
  1267. }
  1268. return lpsz;
  1269. }
  1270. /*************************** Private Function ******************************\
  1271. FreeMem
  1272. \***************************************************************************/
  1273. BOOL FreeMem( HANDLE hmem ) {
  1274. if(GlobalUnlock(hmem)) {
  1275. DOut(hwndMain,"DdeStrs.Exe -- ERR:GlobalUnlock ret=%u (still locked)\n\r",0,(INT)TRUE);
  1276. }
  1277. FreeMemHandle(hmem);
  1278. return TRUE;
  1279. }
  1280. /*************************** Private Function ******************************\
  1281. FreeMemHandle
  1282. \***************************************************************************/
  1283. BOOL FreeMemHandle( HANDLE hmem ) {
  1284. LONG ll;
  1285. ll=GlobalSize(hmem);
  1286. if(!GlobalFree(hmem)) {
  1287. SetCount(hwndMain,OFFSET_MEM_ALLOCATED,ll,DEC);
  1288. }
  1289. else {
  1290. DOut(hwndMain,"DdeStrs.Exe -- ERR:GlobalFree returned %u (not free'd)\n\r",0,(INT)hmem);
  1291. return FALSE;
  1292. }
  1293. return TRUE;
  1294. }
  1295. /**************************** Private *******************************\
  1296. * CreateThreadExtraMem - This routine creates extra thread memory
  1297. * to be used in conjuction with the functions
  1298. * Get/SetThreadLong.
  1299. *
  1300. \********************************************************************/
  1301. BOOL CreateThreadExtraMem( INT nExtra, INT nThrds ) {
  1302. hExtraMem=GetMemHandle(nExtra*nThrds);
  1303. SetWindowLong(hwndMain,OFFSET_EXTRAMEM,nExtra);
  1304. if(hExtraMem==NULL) return FALSE;
  1305. else return TRUE;
  1306. }
  1307. /**************************** Private *******************************\
  1308. * FreeThreadExtraMem - This routine frees extra thread memory
  1309. * to be used in conjuction with the functions
  1310. * Get/SetThreadLong.
  1311. *
  1312. * Note: FreeMemHandle can not be used here because it relies on
  1313. * the main window still being around. At this point our
  1314. * main window has already been destroied.
  1315. *
  1316. \********************************************************************/
  1317. BOOL FreeThreadExtraMem( void ) {
  1318. GlobalFree(hExtraMem);
  1319. return TRUE;
  1320. }
  1321. /**************************** Private *******************************\
  1322. * GetThreadLong - This routine queries the value specified by the
  1323. * nOffset parameter from the threads memory areas
  1324. * specified by the dwid value.
  1325. *
  1326. * Memory layout - thread 1: OFFSET1, OFFSET2, ..., OFFSETN
  1327. * thread 2: OFFSET1, OFFSET2, ..., OFFSETN
  1328. * .
  1329. * .
  1330. * thread n: OFFSET1, OFFSET2, ..., OFFSETN
  1331. *
  1332. \********************************************************************/
  1333. LONG GetThreadLong( DWORD dwid, INT nOffset ) {
  1334. INT nThrd;
  1335. LONG l,lExMem;
  1336. LPBYTE lp;
  1337. LONG FAR *lpl;
  1338. lp=GlobalLock(hExtraMem);
  1339. // Find out which thread is making the call.
  1340. nThrd=IDtoTHREADNUM(dwid);
  1341. // This is the amount of extra memory for one thread.
  1342. lExMem=GetWindowLong(hwndMain,OFFSET_EXTRAMEM);
  1343. // Value at thread and offset. See above for storage layout.
  1344. lpl=(LONG FAR *)(lp+((nThrd-1)*lExMem)+nOffset);
  1345. l=*lpl;
  1346. GlobalUnlock(hExtraMem);
  1347. return l;
  1348. }
  1349. /**************************** Private *******************************\
  1350. * SetThreadLong - This routine sets the value specified by the
  1351. * nOffset parameter from the threads memory areas
  1352. * specified by the dwid value.
  1353. *
  1354. * Memory layout - thread 1: OFFSET1, OFFSET2, ..., OFFSETN
  1355. * thread 2: OFFSET1, OFFSET2, ..., OFFSETN
  1356. * .
  1357. * .
  1358. * thread n: OFFSET1, OFFSET2, ..., OFFSETN
  1359. *
  1360. \********************************************************************/
  1361. LONG SetThreadLong( DWORD dwid, INT nOffset, LONG l ) {
  1362. INT nThrd;
  1363. LONG lPrevValue,lExMem;
  1364. LPBYTE lp;
  1365. LPLONG lpl;
  1366. lp=GlobalLock(hExtraMem);
  1367. // Find out which thread is making the call.
  1368. nThrd=IDtoTHREADNUM(dwid);
  1369. // This is the amount of extra memory for one thread.
  1370. lExMem=GetWindowLong(hwndMain,OFFSET_EXTRAMEM);
  1371. // Value at thread and offset. See above for storage layout.
  1372. lPrevValue=(LONG)(*(lp+((nThrd-1)*lExMem)+nOffset));
  1373. lpl=(LPLONG)(lp+((nThrd-1)*lExMem)+nOffset);
  1374. *lpl=l;
  1375. GlobalUnlock(hExtraMem);
  1376. return lPrevValue;
  1377. }
  1378.