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.

803 lines
21 KiB

  1. /*
  2. ** MEP Party extension
  3. **
  4. ** History:
  5. ** 17-Oct-1991 Ported to NT
  6. **
  7. */
  8. #define _CTYPE_DISABLE_MACROS
  9. #include <ctype.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include "zext.h"
  13. #include <winuserp.h>
  14. #ifndef TRUE
  15. #define TRUE -1
  16. #define FALSE 0
  17. #endif
  18. HWND hwndSelf;
  19. flagType iconizeOnExit = TRUE;
  20. flagType pascal DoCaseLine(
  21. PFILE CurFile,
  22. LINE y,
  23. COL x,
  24. COL maxX,
  25. flagType LowerCase
  26. )
  27. {
  28. flagType Modified;
  29. int cb;
  30. char buf[ BUFLEN ], *s;
  31. cb = GetLine( y, buf, CurFile );
  32. s = &buf[ x ];
  33. if (maxX != 0) {
  34. if (maxX - x < cb) {
  35. cb = maxX - x + 1;
  36. }
  37. }
  38. else {
  39. cb -= x;
  40. }
  41. Modified = FALSE;
  42. while (cb--) {
  43. if (LowerCase) {
  44. if (*s >= 'A' && *s <= 'Z') {
  45. *s -= 'A' - 'a';
  46. Modified = TRUE;
  47. }
  48. }
  49. else {
  50. if (*s >= 'a' && *s <= 'z') {
  51. *s += 'A' - 'a';
  52. Modified = TRUE;
  53. }
  54. }
  55. s++;
  56. }
  57. if (Modified) {
  58. PutLine( y, buf, CurFile );
  59. }
  60. return( TRUE );
  61. }
  62. flagType pascal EXTERNAL
  63. Case(
  64. CMDDATA argData,
  65. ARG far *pArg,
  66. flagType fMeta
  67. )
  68. {
  69. int i;
  70. PFILE CurFile;
  71. CurFile = FileNameToHandle("",NULL);
  72. switch( pArg->argType ) {
  73. case NOARG:
  74. return( DoCaseLine( CurFile, pArg->arg.noarg.y, 0, 0, fMeta ) );
  75. break;
  76. case NULLARG:
  77. return( DoCaseLine( CurFile,
  78. pArg->arg.nullarg.y,
  79. pArg->arg.nullarg.x,
  80. 0,
  81. fMeta
  82. )
  83. );
  84. break;
  85. case LINEARG:
  86. for (i=pArg->arg.linearg.yStart; i<=pArg->arg.linearg.yEnd; i++) {
  87. if (!DoCaseLine( CurFile, (LINE)i, 0, 0, fMeta )) {
  88. return( FALSE );
  89. }
  90. }
  91. return( TRUE );
  92. break;
  93. case BOXARG:
  94. for (i=pArg->arg.boxarg.yTop; i<=pArg->arg.boxarg.yBottom; i++) {
  95. if (!DoCaseLine( CurFile,
  96. (LINE)i,
  97. pArg->arg.boxarg.xLeft,
  98. pArg->arg.boxarg.xRight,
  99. fMeta
  100. )
  101. ) {
  102. return( FALSE );
  103. }
  104. }
  105. return( TRUE );
  106. break;
  107. default:
  108. BadArg();
  109. return( FALSE );
  110. }
  111. argData;
  112. }
  113. int CountMsgFiles;
  114. int MsgFileIndex;
  115. HANDLE MsgFiles[ 2 ];
  116. int MsgFileOffsetIndex;
  117. LONG MsgFileOffsets[ 3 ];
  118. char
  119. GetHexDigit(
  120. ULONG value,
  121. int index
  122. )
  123. {
  124. int digit;
  125. if (index < 4) {
  126. index <<= 2;
  127. digit = (int)((value >> index) & 0xF);
  128. }
  129. else {
  130. digit = 0;
  131. }
  132. if (digit <= 9) {
  133. return( (char)(digit+'0') );
  134. }
  135. else {
  136. return( (char)((digit-10)+'A') );
  137. }
  138. }
  139. void
  140. MyFormatMessage(
  141. char *buf,
  142. char *msg,
  143. long value1,
  144. long value2
  145. );
  146. void
  147. MyFormatMessage(
  148. char *buf,
  149. char *msg,
  150. long value1,
  151. long value2
  152. )
  153. {
  154. char c, *src, *dst;
  155. long value;
  156. src = msg;
  157. dst = buf;
  158. while (c = *src++) {
  159. if (c == '%' && src[1] == 'x') {
  160. if (*src == '1') {
  161. value = value1;
  162. }
  163. else {
  164. value = value2;
  165. }
  166. *dst++ = GetHexDigit( value, 3 );
  167. *dst++ = GetHexDigit( value, 2 );
  168. *dst++ = GetHexDigit( value, 1 );
  169. *dst++ = GetHexDigit( value, 0 );
  170. src++;
  171. src++;
  172. }
  173. else {
  174. *dst++ = c;
  175. }
  176. }
  177. *dst = '\0';
  178. DoMessage( buf );
  179. }
  180. flagType pascal EXTERNAL
  181. ShowBuildMessage(
  182. CMDDATA argData,
  183. ARG far *pArg,
  184. flagType fMeta
  185. )
  186. {
  187. int i, BytesRead, BytesScanned, linenum;
  188. ULONG NewOffset;
  189. char LineBuffer[ 256 ], *s, *s1;
  190. if (!fMeta && CountMsgFiles == 0) {
  191. MsgFileIndex = 0;
  192. MsgFiles[ MsgFileIndex ] = CreateFile( "build.wrn",
  193. GENERIC_READ,
  194. FILE_SHARE_READ,
  195. NULL,
  196. OPEN_EXISTING,
  197. 0,
  198. NULL
  199. );
  200. if (MsgFiles[ MsgFileIndex ] != INVALID_HANDLE_VALUE) {
  201. CountMsgFiles++;
  202. MsgFileIndex++;
  203. }
  204. MsgFiles[ MsgFileIndex ] = CreateFile( "build.err",
  205. GENERIC_READ,
  206. FILE_SHARE_READ,
  207. NULL,
  208. OPEN_EXISTING,
  209. 0,
  210. NULL
  211. );
  212. if (MsgFiles[ MsgFileIndex ] != INVALID_HANDLE_VALUE) {
  213. CountMsgFiles++;
  214. MsgFileIndex++;
  215. }
  216. MsgFileIndex = 0;
  217. MsgFileOffsetIndex = 0;
  218. MsgFileOffsets[ 0 ] = 0L;
  219. MsgFileOffsets[ 1 ] = 0L;
  220. MsgFileOffsets[ 2 ] = 0L;
  221. }
  222. else
  223. if (fMeta && CountMsgFiles != 0) {
  224. for (i=0; i<CountMsgFiles; i++) {
  225. CloseHandle( MsgFiles[ i ] );
  226. }
  227. CountMsgFiles = 0;
  228. return( TRUE );
  229. }
  230. if (CountMsgFiles == 0) {
  231. DoMessage( "No BUILD.WRN or BUILD.ERR message file." );
  232. return( FALSE );
  233. }
  234. switch( pArg->argType ) {
  235. case NULLARG:
  236. if (MsgFileOffsetIndex-- == 0) {
  237. MsgFileOffsetIndex = 2;
  238. }
  239. //
  240. // fall through
  241. //
  242. case NOARG:
  243. retrymsgfile:
  244. NewOffset = SetFilePointer( MsgFiles[ MsgFileIndex ],
  245. MsgFileOffsets[ MsgFileOffsetIndex ],
  246. NULL,
  247. FILE_BEGIN
  248. );
  249. if (NewOffset == -1) {
  250. MyFormatMessage( LineBuffer,
  251. "SetFilePointer( %1x ) failed - rc == %2x",
  252. MsgFileOffsets[ MsgFileOffsetIndex ],
  253. GetLastError()
  254. );
  255. DoMessage( LineBuffer );
  256. return( FALSE );
  257. }
  258. if (!ReadFile( MsgFiles[ MsgFileIndex ],
  259. LineBuffer,
  260. sizeof( LineBuffer ),
  261. ( LPDWORD )&BytesRead,
  262. NULL
  263. )
  264. ) {
  265. MyFormatMessage( LineBuffer,
  266. "ReadFile( %1x ) failed - rc == %2x",
  267. (ULONG)BytesRead,
  268. GetLastError()
  269. );
  270. DoMessage( LineBuffer );
  271. return( FALSE );
  272. }
  273. s = LineBuffer;
  274. BytesScanned = 0;
  275. while (BytesScanned < BytesRead) {
  276. BytesScanned++;
  277. if (*s == '\n') {
  278. *s = '\0';
  279. break;
  280. }
  281. else
  282. if (*s == '\r' && s[1] == '\n') {
  283. *s = '\0';
  284. BytesScanned++;
  285. break;
  286. }
  287. else {
  288. s++;
  289. }
  290. }
  291. if (BytesScanned == 0) {
  292. if (++MsgFileIndex == CountMsgFiles) {
  293. for (i=0; i<CountMsgFiles; i++) {
  294. CloseHandle( MsgFiles[ i ] );
  295. }
  296. CountMsgFiles = 0;
  297. DoMessage( "no more BUILD messages" );
  298. return( FALSE );
  299. }
  300. else {
  301. MsgFileOffsetIndex = 0;
  302. MsgFileOffsets[ 0 ] = 0L;
  303. MsgFileOffsets[ 1 ] = 0L;
  304. MsgFileOffsets[ 2 ] = 0L;
  305. goto retrymsgfile;
  306. }
  307. }
  308. else {
  309. NewOffset = MsgFileOffsets[ MsgFileOffsetIndex ];
  310. if (++MsgFileOffsetIndex == 3) {
  311. MsgFileOffsetIndex = 0;
  312. }
  313. MsgFileOffsets[ MsgFileOffsetIndex ] = NewOffset + BytesScanned;
  314. }
  315. s = LineBuffer;
  316. while (*s) {
  317. if (*s == '(') {
  318. *s++ = '\0';
  319. s1 = s;
  320. while (s1 > LineBuffer && s1[-1] == ' ') {
  321. *--s1 = '\0';
  322. }
  323. s1 = s;
  324. while (*s && isdigit( *s )) {
  325. s++;
  326. }
  327. *s++ = '\0';
  328. linenum = atoi( s1 );
  329. while (*s) {
  330. if (*s++ == ':') {
  331. PFILE pOldFile;
  332. DWORD fOldFileFlags;
  333. //
  334. // Switch to correct file for message. If we change to
  335. // a different file and the old one was modified, write
  336. // it out.
  337. //
  338. pOldFile = FileNameToHandle( "", NULL );
  339. fOldFileFlags = 0;
  340. GetEditorObject( 0xFF | RQ_FILE_FLAGS, pOldFile, (PVOID)&fOldFileFlags );
  341. fChangeFile( FALSE, LineBuffer );
  342. if (pOldFile != FileNameToHandle( "", NULL ) &&
  343. fOldFileFlags & DIRTY) {
  344. FileWrite( "", pOldFile );
  345. }
  346. MoveCur( 0, (LINE)(linenum-1) );
  347. fExecute( "begline" );
  348. DoMessage( s+1 );
  349. return( TRUE );
  350. }
  351. }
  352. }
  353. else {
  354. s++;
  355. }
  356. }
  357. goto retrymsgfile;
  358. default:
  359. BadArg();
  360. return( FALSE );
  361. }
  362. return( TRUE );
  363. argData;
  364. }
  365. char ErrorText[ 64 ],
  366. Arguments[ 64 + MAX_PATH ],
  367. PathName[ MAX_PATH ];
  368. flagType pascal EXTERNAL
  369. SlmOut(
  370. CMDDATA argData,
  371. ARG far *pArg,
  372. flagType fMeta
  373. )
  374. {
  375. PFILE pCurFile;
  376. char *FileName;
  377. DWORD fFileFlags;
  378. char OldCurrentDirectory[MAX_PATH];
  379. pCurFile = FileNameToHandle( (char far *)"", (char far *)NULL );
  380. fFileFlags = 0;
  381. GetEditorObject( 0xFF | RQ_FILE_FLAGS, pCurFile, (PVOID)&fFileFlags );
  382. GetEditorObject( 0xFF | RQ_FILE_NAME, pCurFile, (PVOID)PathName );
  383. FileName = PathName + strlen( PathName );
  384. while (FileName > PathName) {
  385. if (*--FileName == '\\') {
  386. *FileName++ = '\0';
  387. break;
  388. }
  389. }
  390. if (FileName == PathName) {
  391. DoMessage( "Unable to get directory for file" );
  392. return( FALSE );
  393. }
  394. if (GetCurrentDirectory(sizeof(OldCurrentDirectory), OldCurrentDirectory) == 0) {
  395. DoMessage( "Unable to save current directory setting" );
  396. return( FALSE );
  397. }
  398. if (SetCurrentDirectory(PathName) != 0) {
  399. strcpy( Arguments, "arg " );
  400. if (fMeta) {
  401. strcpy( Arguments, "cd & in -i " );
  402. }
  403. else {
  404. strcpy( Arguments, "cd & out -z " );
  405. }
  406. strcat( Arguments, FileName );
  407. strcat( Arguments, " & if ERRORLEVEL 1 pause" );
  408. DoSpawn( Arguments, FALSE );
  409. if (!fMeta && fFileFlags & DIRTY) {
  410. FileWrite( "", pCurFile );
  411. SetEditorObject( 0xFF | RQ_FILE_MODTIME, pCurFile, (PVOID)NULL );
  412. if (fFileFlags & DIRTY) {
  413. DoMessage( "Modified file has been checked out." );
  414. }
  415. else {
  416. DoMessage( "Current file has been checked out." );
  417. }
  418. }
  419. else {
  420. if (fMeta) {
  421. fExecute( "refresh" );
  422. DoMessage( "Changes to current file discarded. No longer checked out." );
  423. }
  424. else {
  425. SetEditorObject( 0xFF | RQ_FILE_MODTIME, pCurFile, (PVOID)NULL );
  426. DoMessage( "Current file has been checked out." );
  427. }
  428. }
  429. SetCurrentDirectory(OldCurrentDirectory);
  430. return( TRUE );
  431. }
  432. else {
  433. DoMessage( "Unable to change current directory" );
  434. return( FALSE );
  435. }
  436. argData;
  437. pArg;
  438. fMeta;
  439. }
  440. HANDLE EditorStartEvent;
  441. HANDLE EditorStopEvent;
  442. HANDLE EditorSharedMemory;
  443. LPSTR EditorMemoryPointer;
  444. HWND hPrevWindow = NULL;
  445. char CommandLineBuffer[ 256 ];
  446. HWND
  447. GetWindowHandleOfEditor( void );
  448. void SwitchToProgram( HWND hwnd );
  449. void
  450. SwitchToTaskManager( void );
  451. flagType pascal EXTERNAL
  452. StartExt(
  453. CMDDATA argData,
  454. ARG far *pArg,
  455. flagType fMeta
  456. )
  457. {
  458. PFILE pCurFile;
  459. int fFileFlags;
  460. if (!fMeta) {
  461. pCurFile = FileNameToHandle( "", NULL );
  462. fFileFlags = 0;
  463. GetEditorObject( 0xFF | RQ_FILE_FLAGS, pCurFile, (PVOID)&fFileFlags );
  464. if (fFileFlags & DIRTY)
  465. FileWrite( "", pCurFile );
  466. }
  467. if (hPrevWindow) {
  468. SetEvent( EditorStopEvent );
  469. SwitchToProgram( hPrevWindow );
  470. hPrevWindow = NULL;
  471. }
  472. else {
  473. SwitchToTaskManager();
  474. }
  475. fExecute( "savetmpfile" );
  476. return TRUE;
  477. argData;
  478. pArg;
  479. }
  480. #if _MSC_FULL_VER >= 13008827
  481. #pragma warning(push)
  482. #pragma warning(disable:4715) // Not all control paths return (due to infinite loop)
  483. #endif
  484. DWORD
  485. WaitForStartEventThread(
  486. PVOID Parameter
  487. )
  488. {
  489. CHAR szFileName[ 256 ];
  490. LPSTR s, lpName, lpValue, lpNewCmdLine, lpEditorMem;
  491. PINPUT_RECORD pEvent, pEvents;
  492. DWORD NumberOfEvents, NumberOfEventsWritten;
  493. while (TRUE) {
  494. WaitForSingleObject( EditorStartEvent, INFINITE );
  495. lpEditorMem = EditorMemoryPointer;
  496. hPrevWindow = *(HWND *)lpEditorMem;
  497. lpEditorMem += sizeof( hPrevWindow );
  498. SetCurrentDirectory( lpEditorMem );
  499. while( *lpEditorMem++ ) {
  500. }
  501. lpNewCmdLine = CommandLineBuffer;
  502. while( *lpNewCmdLine++ = *lpEditorMem++ ) {
  503. }
  504. while (*lpEditorMem) {
  505. lpName = lpEditorMem;
  506. while (*lpEditorMem) {
  507. if (*lpEditorMem++ == '=') {
  508. lpValue = lpEditorMem;
  509. lpValue[ -1 ] = '\0';
  510. while (*lpEditorMem++) {
  511. }
  512. SetEnvironmentVariableA( lpName, lpValue );
  513. lpValue[ -1 ] = '=';
  514. break;
  515. }
  516. }
  517. }
  518. s = CommandLineBuffer;
  519. while (*s == ' ')
  520. s++;
  521. if (*s) {
  522. NumberOfEvents = 1 + strlen( s ) + 1;
  523. pEvents = HeapAlloc( GetProcessHeap(), 0, NumberOfEvents * sizeof( *pEvent ) );
  524. pEvent = pEvents;
  525. pEvent->EventType = KEY_EVENT;
  526. FuncNameToKeyEvent( "arg", &pEvent->Event.KeyEvent);
  527. pEvent += 1;
  528. while (*s) {
  529. pEvent->EventType = KEY_EVENT;
  530. FuncNameToKeyEvent( (char *)(BYTE)*s++, &pEvent->Event.KeyEvent);
  531. pEvent += 1;
  532. }
  533. pEvent->EventType = KEY_EVENT;
  534. FuncNameToKeyEvent( "setfile", &pEvent->Event.KeyEvent);
  535. pEvent += 1;
  536. WriteConsoleInput( GetStdHandle( STD_INPUT_HANDLE ),
  537. pEvents,
  538. NumberOfEvents,
  539. &NumberOfEventsWritten
  540. );
  541. HeapFree( GetProcessHeap(), 0, pEvents );
  542. }
  543. }
  544. return TRUE;
  545. }
  546. #if _MSC_FULL_VER >= 13008827
  547. #pragma warning(pop)
  548. #endif
  549. void
  550. SwitchToProgram(
  551. HWND hwnd
  552. )
  553. {
  554. if (hwndSelf && iconizeOnExit) {
  555. ShowWindow( hwndSelf, SW_MINIMIZE );
  556. }
  557. SetForegroundWindow( hwnd );
  558. ShowWindow( hwnd, SW_RESTORE);
  559. }
  560. void
  561. SwitchToTaskManager( void )
  562. {
  563. HWND hwnd;
  564. wchar_t szTitle[ 256 ];
  565. /*
  566. * Search the window list for task manager window.
  567. */
  568. hwnd = GetWindow( GetDesktopWindow(), GW_CHILD );
  569. while (hwnd) {
  570. /*
  571. * Only look at non-visible, non-owned, Top Level Windows.
  572. */
  573. if (!IsWindowVisible( hwnd ) && !GetWindow( hwnd, GW_OWNER )) {
  574. //
  575. // Use internal call to get current Window title that does NOT
  576. // use SendMessage to query the title from the window procedure
  577. // but instead returns the most recent title displayed.
  578. //
  579. InternalGetWindowText( hwnd,
  580. (LPWSTR)szTitle,
  581. sizeof( szTitle )
  582. );
  583. if (!_wcsicmp( L"Task List", szTitle )) {
  584. SwitchToProgram( hwnd );
  585. break;
  586. }
  587. }
  588. hwnd = GetWindow( hwnd, GW_HWNDNEXT );
  589. }
  590. return;
  591. }
  592. flagType
  593. StartExtLoaded( void );
  594. flagType
  595. StartExtLoaded ()
  596. {
  597. HANDLE Thread;
  598. DWORD ThreadId;
  599. hwndSelf = GetWindowHandleOfEditor();
  600. EditorStartEvent = CreateEvent( NULL, FALSE, FALSE, "EditorStartEvent" );
  601. if (EditorStartEvent == NULL) {
  602. DoMessage( "Create of EditorStartEvent failed" );
  603. return FALSE;
  604. }
  605. EditorStopEvent = CreateEvent( NULL, FALSE, FALSE, "EditorStopEvent" );
  606. if (EditorStopEvent == NULL) {
  607. DoMessage( "Create of EditorStopEvent failed" );
  608. CloseHandle( EditorStartEvent );
  609. return FALSE;
  610. }
  611. EditorSharedMemory = CreateFileMapping( INVALID_HANDLE_VALUE,
  612. NULL,
  613. PAGE_READWRITE,
  614. 0,
  615. 8192,
  616. "EditorSharedMemory"
  617. );
  618. if (EditorSharedMemory == NULL) {
  619. DoMessage( "Create of EditorStartMemory failed" );
  620. CloseHandle( EditorStopEvent );
  621. CloseHandle( EditorStartEvent );
  622. return FALSE;
  623. }
  624. EditorMemoryPointer = MapViewOfFile( EditorSharedMemory,
  625. FILE_MAP_READ | FILE_MAP_WRITE,
  626. 0,
  627. 0,
  628. 8192
  629. );
  630. if (EditorMemoryPointer == NULL) {
  631. DoMessage( "MapView of EditorStartMemory failed" );
  632. CloseHandle( EditorStopEvent );
  633. CloseHandle( EditorStartEvent );
  634. CloseHandle( EditorSharedMemory );
  635. return FALSE;
  636. }
  637. Thread = CreateThread( NULL,
  638. 8192,
  639. (LPTHREAD_START_ROUTINE)WaitForStartEventThread,
  640. 0,
  641. 0,
  642. &ThreadId
  643. );
  644. if (Thread == NULL) {
  645. DoMessage( "Can't start environment thread" );
  646. UnmapViewOfFile( EditorMemoryPointer );
  647. CloseHandle( EditorSharedMemory );
  648. CloseHandle( EditorStopEvent );
  649. CloseHandle( EditorStartEvent );
  650. return FALSE;
  651. }
  652. if (!SetThreadPriority( Thread, THREAD_PRIORITY_ABOVE_NORMAL )) {
  653. DoMessage( "Can't set priority of environment thread" );
  654. }
  655. CloseHandle( Thread );
  656. return TRUE;
  657. }
  658. void partyWhenLoaded(void)
  659. {
  660. if (StartExtLoaded()) {
  661. CountMsgFiles = 0;
  662. }
  663. }
  664. HWND
  665. GetWindowHandleOfEditor( void )
  666. {
  667. #define MY_BUFSIZE 1024 // buffer size for console window titles
  668. HWND hwndFound; // this is what we return to the caller
  669. char pszNewWindowTitle[ MY_BUFSIZE ]; // contains fabricated WindowTitle
  670. char pszOldWindowTitle[ MY_BUFSIZE ] = {0}; // contains original WindowTitle
  671. // fetch current window title
  672. GetConsoleTitle( pszOldWindowTitle, MY_BUFSIZE );
  673. // format a "unique" NewWindowTitle
  674. wsprintf( pszNewWindowTitle, "%d/%d", GetTickCount(), GetCurrentProcessId() );
  675. // change current window title
  676. SetConsoleTitle( pszNewWindowTitle );
  677. // insure window title has been updated
  678. Sleep(40);
  679. // look for NewWindowTitle
  680. hwndFound = FindWindow( NULL, pszNewWindowTitle );
  681. // restore original window title
  682. SetConsoleTitle( pszOldWindowTitle );
  683. return( hwndFound );
  684. }