launch.c

Go to the documentation of this file.
00001 
00002 /*  $Id: launch.c 1203 2006-04-05 22:58:09Z karstenw $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #include "frontier.h"
00029 #include "standard.h"
00030 
00031 #ifdef MACVERSION
00032 #include <land.h>
00033 #include "mac.h"
00034 #endif
00035 
00036 #include "error.h"
00037 #include "memory.h"
00038 #include "strings.h"
00039 #include "file.h"
00040 #include "launch.h"
00041 #include "threads.h"
00042 
00043 #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
00044     #include "aeutils.h"
00045 #endif
00046 
00047 #ifdef MACVERSION
00048 
00049 typedef struct typrocessvisitinfo { /*2002-11-14 AR: for providing context to visitprocesses callbacks*/
00050     OSType idprocess;
00051     short ctprocesses;
00052     short nthprocess;
00053     ptrstring bsprocess;
00054     typrocessid *psnprocess;
00055     tyfilespec *fsprocess;
00056     } typrocessvisitinfo;
00057     
00058 typedef struct typrocessvisitinfo *typrocessvisitinfoptr;
00059 
00060 #define initprocessvisitinfo(x) \
00061     do {                        \
00062     (x)->idprocess = 0L;        \
00063     (x)->ctprocesses = 0;       \
00064     (x)->nthprocess = 0;        \
00065     (x)->bsprocess = NULL;      \
00066     (x)->psnprocess = NULL;     \
00067     (x)->fsprocess = NULL;      \
00068     } while(0)
00069 
00070 #endif
00071 
00072 tylaunchcallbacks launchcallbacks = {nil};
00073 
00074 #define maxwait 120 /*never wait more than 2 seconds for a stransition to occur*/
00075 
00076 #ifdef flsystem6
00077 
00078 typedef struct system6launchparamblock {
00079     StringPtr               name;
00080     unsigned short          reserved1;
00081     unsigned short          launchBlockID;
00082     unsigned long           launchEPBLength;
00083     unsigned short          launchFileFlags;
00084     LaunchFlags             launchControlFlags;
00085     unsigned short          launchVRefNum;
00086 } system6launchparamblock;
00087 
00088 #endif
00089 
00090 
00091 #ifdef MACVERSION
00092 typedef AppParameters **AppParametersHandle;
00093 #endif
00094 
00095 
00096 #ifdef WIN95VERSION
00097 typedef struct tyWINPROCESSINFO
00098     {
00099     struct tyWINPROCESSINFO ** next;
00100     bigstring ModName;
00101     bigstring ExeName;
00102     DWORD processID;
00103     HWND windowHandle;
00104     boolean isWindowVisible;
00105     } WINPROCESSINFO;
00106 
00107 typedef struct tyWINPROCESSHEADER
00108     {
00109     long count;
00110     long platform;          //0 for win95; 1 for winNT
00111     long windowCount;
00112     HWND windowList[1024];
00113     WINPROCESSINFO ** head;
00114     } WINPROCESSHEADER;
00115 
00116 
00117 // Type definitions for pointers to call tool help functions. 
00118 typedef BOOL (WINAPI *MODULEWALK)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
00119 typedef BOOL (WINAPI *PROCESSWALK)(HANDLE hSnapshot, LPPROCESSENTRY32 lppe); 
00120 typedef HANDLE (WINAPI *CREATESNAPSHOT)(DWORD dwFlags, DWORD th32ProcessID); 
00121  
00122 // File scope globals. These pointers are declared because of the need 
00123 // to dynamically link to the functions.  They are exported only by 
00124 // the Windows 95 kernel. Explicitly linking to them will make this 
00125 // application unloadable in Microsoft(R) Windows NT(TM) and will 
00126 // produce an ugly system dialog box. 
00127 static CREATESNAPSHOT pCreateToolhelp32Snapshot = NULL; 
00128 static MODULEWALK  pModule32First  = NULL;
00129 static MODULEWALK  pModule32Next   = NULL;
00130 static PROCESSWALK pProcess32First = NULL; 
00131 static PROCESSWALK pProcess32Next  = NULL; 
00132  
00133 // Function that initializes tool help functions. 
00134 static BOOL InitToolhelp32 (void) 
00135     { 
00136     BOOL   bRet  = FALSE; 
00137     HANDLE hKernel = NULL; 
00138  
00139     if ((pCreateToolhelp32Snapshot != NULL) && 
00140         (pModule32First != NULL) && (pModule32Next != NULL) &&
00141         (pProcess32First != NULL) && (pProcess32Next != NULL))
00142         return (true);  /*already done*/
00143 
00144 
00145     // Obtain the module handle of the kernel to retrieve addresses of 
00146     // the tool helper functions. 
00147     hKernel = GetModuleHandle("KERNEL32.DLL"); 
00148  
00149     if (hKernel) { 
00150         pCreateToolhelp32Snapshot = (CREATESNAPSHOT)GetProcAddress(hKernel, "CreateToolhelp32Snapshot"); 
00151  
00152         pModule32First  = (MODULEWALK)GetProcAddress(hKernel, "Module32First");
00153         pModule32Next   = (MODULEWALK)GetProcAddress(hKernel, "Module32Next");
00154 
00155         pProcess32First = (PROCESSWALK)GetProcAddress(hKernel, "Process32First"); 
00156         pProcess32Next  = (PROCESSWALK)GetProcAddress(hKernel, "Process32Next"); 
00157  
00158         // All addresses must be non-NULL to be successful. 
00159         // If one of these addresses is NULL, one of 
00160         // the needed lists cannot be walked. 
00161         bRet =  pProcess32First && 
00162                 pProcess32Next &&
00163                 pModule32First &&
00164                 pModule32Next &&
00165                 pCreateToolhelp32Snapshot; 
00166         } 
00167     else 
00168         bRet = FALSE; // could not even get the module handle of kernel 
00169  
00170     return bRet; 
00171     } /*InitToolhelp32*/
00172 
00173 
00174 // Type definitions for pointers to call PSAPI. 
00175 typedef BOOL (WINAPI *PSAPIENUMPROCESS)(DWORD * lpidProcess, DWORD cb, DWORD * cbNeeded);
00176 typedef BOOL (WINAPI *PSAPIENUMPROCESSMODULES)(HANDLE hProcess, HMODULE * lphModule, DWORD cb, LPDWORD lpcbNeeded); 
00177 typedef DWORD (WINAPI *PSAPIGETMODULENAME)(HANDLE hProcess, HMODULE hModule, LPSTR lpName, DWORD nSize); 
00178  
00179 // File scope globals. These pointers are declared because of the need 
00180 // to dynamically link to the functions.  They are exported only by 
00181 // the Windows NT PSAPI.DLL. Explicitly linking to them will make this 
00182 // application unloadable in Microsoft(R) Windows 95(TM) and will 
00183 // produce an ugly system dialog box. 
00184 static PSAPIENUMPROCESS pEnumProcesses = NULL; 
00185 static PSAPIENUMPROCESSMODULES  pEnumProcessModules  = NULL;
00186 static PSAPIGETMODULENAME pGetModuleBaseName   = NULL;
00187 static PSAPIGETMODULENAME pGetModuleFileNameEx = NULL; 
00188 
00189 // Function that initializes Process Apps functions. 
00190 static BOOL InitToolhelpNT (void) 
00191     { 
00192     BOOL   bRet  = FALSE; 
00193     HANDLE hKernel = NULL; 
00194  
00195     if ((pEnumProcesses != NULL) && 
00196         (pEnumProcessModules != NULL) && (pGetModuleBaseName != NULL) &&
00197         (pGetModuleFileNameEx != NULL))
00198         return (true);  /*already done*/
00199 
00200 
00201     // Obtain the module handle of the kernel to retrieve addresses of 
00202     // the tool helper functions. 
00203     hKernel = LoadLibrary("PSAPI.DLL"); 
00204  
00205     if (hKernel){ 
00206         pEnumProcesses = (PSAPIENUMPROCESS)GetProcAddress(hKernel, "EnumProcesses"); 
00207         pEnumProcessModules  = (PSAPIENUMPROCESSMODULES)GetProcAddress(hKernel, "EnumProcessModules");
00208 
00209         pGetModuleBaseName = (PSAPIGETMODULENAME)GetProcAddress(hKernel, "GetModuleBaseNameA"); 
00210         pGetModuleFileNameEx  = (PSAPIGETMODULENAME)GetProcAddress(hKernel, "GetModuleFileNameExA"); 
00211  
00212         // All addresses must be non-NULL to be successful. 
00213         // If one of these addresses is NULL, one of 
00214         // the needed lists cannot be walked. 
00215         bRet =  pEnumProcesses && 
00216                 pEnumProcessModules &&
00217                 pGetModuleBaseName &&
00218                 pGetModuleFileNameEx; 
00219     } 
00220     else 
00221         bRet = FALSE; // could not even get the module handle of kernel 
00222  
00223     return bRet; 
00224 } 
00225 
00226 
00227 
00228 //
00229 //  FUNCTION: GetModuleNameFromExe(LPCSTR, LPSTR, WORD)
00230 //
00231 //  PURPOSE:  Retrieves the module name of a Win16 app or DLL from its
00232 //            excutable file.
00233 //
00234 //  PARAMETERS:
00235 //    szFileName   - Executable file (.EXE or .DLL) from which to retrieve 
00236 //                   module name
00237 //    szModuleName - Points to buffer that receives the module name
00238 //    cbLen        - Specifies maximum length of szModuleName including NULL
00239 //
00240 //  RETURN VALUE:
00241 //    TRUE if the module name was succesfully copied into szModuleName.
00242 //    FALSE if it wasn't killed.
00243 //
00244 //  COMMENTS:
00245 //    Works for Win16 New Executable files only.
00246 //
00247 
00248 static BOOL GetModuleNameFromExe (LPCSTR szFileName, LPSTR szModuleName, WORD cbLen)
00249 {
00250 
00251 #ifdef _MSC_VER
00252 
00253     BOOL              bResult      = FALSE;
00254     HANDLE            hFile        = NULL;
00255     HANDLE            hFileMapping = NULL;
00256     PIMAGE_OS2_HEADER pNEHdr       = NULL;
00257     PIMAGE_DOS_HEADER pDosExeHdr   = NULL;
00258 
00259     // Open the file as read-only.  (This file may be opened already by the
00260     // system if it is an application or DLL that is currently loaded.)
00261     // Create a read-only file mapping and map a read-only view of the file.
00262     // If we can't open the file for some reason, then return FALSE.
00263   
00264     hFile = CreateFile(szFileName,
00265                        GENERIC_READ,
00266                        FILE_SHARE_READ|FILE_SHARE_WRITE,
00267                        NULL,
00268                        OPEN_EXISTING,
00269                        0,
00270                        NULL);
00271  
00272     if (hFile == INVALID_HANDLE_VALUE)
00273         return FALSE;
00274  
00275     hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
00276     if (hFileMapping == NULL)
00277     {
00278         verify (CloseHandle(hFile));
00279         return FALSE;
00280     }
00281  
00282     pDosExeHdr = (PIMAGE_DOS_HEADER)MapViewOfFile (hFileMapping,
00283                                                    FILE_MAP_READ,
00284                                                    0,
00285                                                    0,
00286                                                    0);
00287     if (!pDosExeHdr)
00288     {
00289         verify (CloseHandle(hFileMapping));
00290         verify (CloseHandle(hFile));
00291         return FALSE;
00292     }
00293  
00294     __try
00295     {
00296         // Go to the beginning of the NE header.
00297         pNEHdr =
00298            (PIMAGE_OS2_HEADER)((LPSTR)pDosExeHdr + pDosExeHdr -> e_lfanew);
00299  
00300         // Check to make sure that the file has DOS and NE EXE headers
00301         if (pDosExeHdr -> e_magic == IMAGE_DOS_SIGNATURE
00302             && pNEHdr -> ne_magic == IMAGE_OS2_SIGNATURE)
00303         {
00304             lstrcpyn (szModuleName, (LPSTR)pNEHdr + pNEHdr -> ne_restab +1,  
00305                       min((BYTE)*((LPSTR)pNEHdr + pNEHdr -> ne_restab) + 1, 
00306                           cbLen));
00307             bResult = TRUE;
00308         }
00309         else
00310             bResult = FALSE;
00311  
00312     }
00313     __except (EXCEPTION_EXECUTE_HANDLER)
00314     {
00315         // If an access violation occurs in the try block, we know the file
00316         // is not a NE file because it is too small to have a NE header, or
00317         // the offset of the NE header isn't close to being correct.
00318         bResult = FALSE;
00319     }
00320  
00321     // Clean up file mapping, all views of file mapping, and close the
00322     // file.
00323     UnmapViewOfFile(pDosExeHdr);
00324     verify (CloseHandle(hFileMapping));
00325     verify (CloseHandle(hFile));
00326  
00327     return bResult;
00328 
00329 #else
00330     
00331     /*
00332     2002-11-10 AR: The Metrowerks Codewarrior compiler for x86 does not appear
00333     to support the __try/__except statements used in the implementation above.
00334     Since it is probably not a good idea to use the same file-mapped i/o code
00335     as above without being able to catch access violations, we simply rewrote
00336     the code to use simple SetFilePointer and ReadFile calls.
00337     */
00338 
00339     BOOL                bResult     = FALSE;
00340     HANDLE              hFile       = NULL;
00341     IMAGE_DOS_HEADER    sDosHeader;
00342     IMAGE_OS2_HEADER    sOs2Header;
00343     DWORD               nResult;
00344     BYTE                nLength;
00345     long                nBytesToRead;
00346     long                nBytesRead; 
00347 
00348     // Open the file as read-only.  (This file may be opened already by the
00349     // system if it is an application or DLL that is currently loaded.)
00350     // If we can't open the file for some reason, then return FALSE.
00351 
00352     hFile = CreateFile(szFileName,
00353                         GENERIC_READ,
00354                         FILE_SHARE_READ|FILE_SHARE_WRITE,
00355                         NULL,
00356                         OPEN_EXISTING,
00357                         0,
00358                         NULL);
00359  
00360     if (hFile == INVALID_HANDLE_VALUE)
00361         return FALSE;
00362 
00363     /* read IMAGE_DOS_HEADER from beginning of file */
00364     
00365     nBytesToRead = sizeof(sDosHeader);
00366     
00367     nResult = ReadFile (hFile, &sDosHeader, nBytesToRead, &nBytesRead, NULL);
00368     
00369     if (!nResult || nBytesRead != nBytesToRead)
00370         goto EXIT;
00371 
00372     /* make sure the data has got the magic signature */
00373     
00374     if (sDosHeader.e_magic != IMAGE_DOS_SIGNATURE)
00375         goto EXIT;
00376     
00377     /* read IMAGE_OS2_HEADER */
00378     
00379     nResult = SetFilePointer (hFile, sDosHeader.e_lfanew, NULL, FILE_BEGIN);
00380     
00381     if (nResult == INVALID_SET_FILE_POINTER)
00382         goto EXIT;
00383     
00384     nBytesToRead = sizeof(sOs2Header);
00385 
00386     nResult = ReadFile (hFile, &sOs2Header, nBytesToRead, &nBytesRead, NULL);
00387     
00388     if (!nResult || nBytesRead != nBytesToRead)
00389         goto EXIT;
00390 
00391     /* make sure the data has got the magic signature */
00392     
00393     if (sOs2Header.ne_magic != IMAGE_OS2_SIGNATURE)
00394         goto EXIT;
00395     
00396     /* read module name from file, first byte is length of name excl. trailing nil */
00397     
00398     nResult = SetFilePointer (hFile, sDosHeader.e_lfanew + sOs2Header.ne_restab, NULL, FILE_BEGIN);
00399     
00400     if (nResult == INVALID_SET_FILE_POINTER)
00401         goto EXIT;
00402     
00403     nBytesToRead = 1;
00404 
00405     nResult = ReadFile (hFile, &nLength, nBytesToRead, &nBytesRead, NULL);
00406     
00407     if (!nResult || nBytesRead != nBytesToRead)
00408         goto EXIT;
00409 
00410     nBytesToRead = min(nLength+1, cbLen);
00411     
00412     nResult = ReadFile (hFile, &szModuleName, nBytesToRead, &nBytesRead, NULL);
00413     
00414     if (!nResult || nBytesRead != nBytesToRead)
00415         goto EXIT;
00416     
00417     bResult = TRUE;
00418 
00419 EXIT:
00420 
00421     verify (CloseHandle(hFile));
00422 
00423     return bResult;
00424 
00425 #endif
00426 }
00427  
00428 
00429 //
00430 //  FUNCTION: GetProcessModule(DWORD, DWORD, LPMODULEENTRY32, DWORD)
00431 //
00432 //  PURPOSE:  Given a Process ID and module ID, return its module information.
00433 //
00434 //  PARAMETERS:
00435 //    dwPID      - ID of process that owns the module we want information 
00436 //                 about.
00437 //    dwModuleID - ToolHelp32 ID of the module within the process
00438 //    lpMe32     - Structure to return data about the module we want
00439 //    cbMe32     - Size of the buffer pointed to by lpMe32--to make sure we 
00440 //                 don't copy too much data into lpMe32.
00441 //
00442 //  RETURN VALUE:
00443 //    TRUE if it returns information about the specifed module.
00444 //    FALSE if it could not enumerate the modules in the process, or the
00445 //          module is not found in the process.
00446 //
00447 //  COMMENTS:
00448 //
00449 
00450 static BOOL GetProcessModule (DWORD           dwPID, 
00451                        DWORD           dwModuleID, 
00452                        LPMODULEENTRY32 lpMe32, 
00453                        DWORD           cbMe32)
00454 {   
00455     BOOL          bRet        = FALSE;
00456     BOOL          bFound      = FALSE;
00457     HANDLE        hModuleSnap = NULL;
00458     MODULEENTRY32 me32        = {0};
00459 
00460     // Take a snapshot of all modules in the specified process.
00461     hModuleSnap = pCreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
00462     if (hModuleSnap == (HANDLE)-1)
00463         return (FALSE);
00464 
00465     // Size of the MODULEENTRY32 structure must be initialized before use!
00466     me32.dwSize = sizeof(MODULEENTRY32);
00467 
00468     // Walk the module list of the process and find the module we are 
00469     // interested in.  Then, copy the information to the buffer pointed to
00470     // by lpMe32 so that we can return it to the caller.
00471     if (pModule32First(hModuleSnap, &me32))
00472     {
00473         do 
00474         {
00475             if (me32.th32ModuleID == dwModuleID)
00476             {
00477                 CopyMemory (lpMe32, &me32, cbMe32);
00478                 bFound = TRUE;
00479             }
00480         }
00481         while (!bFound && pModule32Next(hModuleSnap, &me32));
00482 
00483         bRet = bFound;   // If this sets bRet to FALSE, then dwModuleID 
00484                          // no longer exsists in the specified process.
00485     }
00486     else
00487         bRet = FALSE;    // Couldn't walk module list.
00488 
00489     // Don't forget to clean up the snapshot object...
00490     verify (CloseHandle (hModuleSnap));
00491 
00492     return (bRet);
00493     } /*GetProcessModule*/
00494 
00495 
00496 static WINPROCESSINFO ** getprocessinfofrompid (WINPROCESSHEADER * ph, DWORD pid) {
00497     WINPROCESSINFO ** entry;
00498 
00499     entry = ph->head;
00500 
00501     while (entry != NULL) {
00502         if ((**entry).processID == pid)
00503             return (entry);
00504 
00505         entry = (**entry).next;
00506         }
00507 
00508     return (NULL);
00509     } /*getprocessinfofrompid*/
00510 
00511 
00512 //static WINPROCESSINFO ** getprocessinfofromhwnd (WINPROCESSHEADER * ph, HWND hwnd) {
00513 //  WINPROCESSINFO ** entry;
00514 //
00515 //  entry = ph->head;
00516 //
00517 //  while (entry != NULL) {
00518 //      if ((**entry).windowHandle == hwnd)
00519 //          return (entry);
00520 //
00521 //      entry = (**entry).next;
00522 //      }
00523 //
00524 //  return (NULL);
00525 //  } /*getprocessinfofromhwnd*/
00526 //
00527 
00528 static WINPROCESSINFO ** getprocessinfofromwintitle (WINPROCESSHEADER * ph, bigstring bsname) {
00529     WINPROCESSINFO ** entry;
00530     char wintitle[258];
00531     short i;
00532     DWORD pid;
00533 
00534     releasethreadglobals ();
00535 
00536     for (i = 0; i < ph->windowCount; i++) {
00537         if (GetWindowText (ph->windowList[i], stringbaseaddress (wintitle), 256)) {
00538             setstringlength (wintitle, strlen(stringbaseaddress(wintitle)));
00539 
00540             if (equalidentifiers (wintitle, bsname)) {
00541                 GetWindowThreadProcessId (ph->windowList[i], &pid);
00542 
00543                 entry = getprocessinfofrompid (ph, pid);
00544 
00545                 if (entry != NULL) {
00546                     (**entry).windowHandle = ph->windowList[i];
00547                     (**entry).isWindowVisible = IsWindowVisible (ph->windowList[i]);
00548                     }
00549 
00550                 grabthreadglobals ();
00551                 return (entry);
00552                 }
00553             }
00554         }
00555 
00556     grabthreadglobals ();
00557     return (NULL);
00558     } /*getprocessinfofromwintitle*/
00559 
00560 
00561 static WINPROCESSINFO ** getprocessinfofrommodname (WINPROCESSHEADER * ph, bigstring bsname) {
00562     WINPROCESSINFO ** entry;
00563 
00564     entry = ph->head;
00565 
00566     while (entry != NULL) {
00567         if (equalidentifiers ((**entry).ModName, bsname))
00568             return (entry);
00569 
00570         entry = (**entry).next;
00571         }
00572 
00573     return (NULL);
00574     } /*getprocessinfofrommodname*/
00575 
00576 
00577 static WINPROCESSINFO ** getprocessinfofromexepath (WINPROCESSHEADER * ph, bigstring bspath) {
00578     WINPROCESSINFO ** entry;
00579 
00580     entry = ph->head;
00581 
00582     while (entry != NULL) {
00583         if (equalidentifiers ((**entry).ExeName, bspath))
00584             return (entry);
00585 
00586         entry = (**entry).next;
00587         }
00588 
00589     return (NULL);
00590     } /*getprocessinfofromexepath*/
00591 
00592 
00593 static BOOL CALLBACK winHandleEnumProc (HWND hwnd, LPARAM lparam) {
00594     WINPROCESSHEADER * listheader;
00595     DWORD pid;
00596     WINPROCESSINFO ** pe;
00597 
00598     listheader = (WINPROCESSHEADER *) lparam;
00599 
00600 //  releasethreadglobals ();
00601         
00602     if (listheader->windowCount < 1024) {
00603         listheader->windowList[listheader->windowCount] = hwnd;
00604 
00605         ++listheader->windowCount;
00606         }
00607 
00608     GetWindowThreadProcessId (hwnd, &pid);
00609 
00610     pe = getprocessinfofrompid (listheader, pid);
00611 
00612     if (pe != NULL) {
00613         if ((**pe).windowHandle != NULL) {
00614             if (! (**pe).isWindowVisible) {
00615                 if (IsWindowVisible (hwnd)) {
00616                     (**pe).windowHandle = hwnd;
00617 
00618                     (**pe).isWindowVisible = true;
00619                     }
00620                 }
00621             }
00622         else {
00623             (**pe).isWindowVisible = IsWindowVisible (hwnd);
00624 
00625             (**pe).windowHandle = hwnd;
00626             }
00627         }
00628 
00629 //  grabthreadglobals ();
00630 
00631     return (true);  /* keep enumerating */
00632     } /*winHandleEnumProc*/
00633 
00634 
00635 static WINPROCESSINFO ** addentrytolist (WINPROCESSHEADER * ph) {
00636 
00637     WINPROCESSINFO * entry;
00638     WINPROCESSINFO ** entryHandle;
00639 
00640     newhandle (sizeof(WINPROCESSINFO), (Handle *)&entryHandle);
00641 
00642     assert (entryHandle);
00643 
00644     lockhandle ((Handle)entryHandle);
00645 
00646     entry = *entryHandle;
00647 
00648     ph->count += 1;
00649 
00650     entry->next = ph->head;
00651     entry->windowHandle = NULL;
00652     entry->isWindowVisible = false;
00653 
00654     ph->head = entryHandle;
00655 
00656     unlockhandle ((Handle)entryHandle);
00657 
00658     return (entryHandle);
00659     } /*addentrytolist*/
00660 
00661 
00662 static void addprocesstolist (WINPROCESSHEADER * ph, PROCESSENTRY32 * pe) {
00663 
00664     WINPROCESSINFO * entry;
00665     WINPROCESSINFO ** entryHandle;
00666     MODULEENTRY32 me32;
00667     BOOL bGotModule;
00668 
00669     entryHandle = addentrytolist (ph);
00670 
00671     assert (entryHandle);
00672 
00673     lockhandle ((Handle)entryHandle);
00674 
00675     entry = *entryHandle;
00676 
00677     entry->processID = pe->th32ProcessID;
00678 
00679     copyctopstring (pe->szExeFile, entry->ExeName);
00680 
00681     bGotModule = GetProcessModule(pe->th32ProcessID, 
00682                                   pe->th32ModuleID, 
00683                                   &me32, 
00684                                   sizeof(MODULEENTRY32));
00685     if (bGotModule)
00686         {
00687 
00688         // Test to see if the app is a Win16 or Win32 app.  If the
00689         // file name returned in the PROCESSENTRY32 and MODULEENTRY32
00690         // structures are equal, then we have a Win32 app, otherwise,
00691         // we have a Win16 app.  
00692 
00693         if (!lstrcmpi (pe->szExeFile, me32.szExePath))
00694             {
00695             // Win32 app, use MODULENETRY32 module name
00696             copyctopstring(me32.szModule, entry->ModName);
00697             }
00698         else
00699             {
00700             // Win16 app, get module name out of EXE header of file
00701             if (!GetModuleNameFromExe (pe->szExeFile, stringbaseaddress(entry->ModName),
00702                                        sizeof(entry->ModName) - 1))
00703                 {
00704                 // If we can't get the module name for some reason, at
00705                 // least put something in the module name.
00706                 copyctopstring(me32.szModule, entry->ModName);
00707                 }
00708             else {
00709                 setstringlength (entry->ModName, strlen(stringbaseaddress(entry->ModName)));
00710                 }
00711             }
00712         }
00713 
00714     unlockhandle ((Handle)entryHandle);
00715     } /*addprocesstolist*/
00716 
00717         
00718 static void cleanProcessHeader (WINPROCESSHEADER * ph) {
00719 
00720     WINPROCESSINFO ** entry;
00721     WINPROCESSINFO ** next;
00722 
00723     entry = ph->head;
00724 
00725     while (entry != NULL) {
00726         next = (**entry).next;
00727         disposehandle((Handle)entry);
00728         entry = next;
00729         }
00730 
00731     ph->count = 0;
00732     ph->windowCount = 0;
00733     ph->head = NULL;
00734     } /*cleanProcessHeader*/
00735 
00736 static void AddNTProcessInfo (WINPROCESSHEADER * listheader, DWORD processID) {
00737     char szProcessName[MAX_PATH] = "unknown";
00738     char szProcessPath[MAX_PATH] = "unknown";
00739     WINPROCESSINFO * entry;
00740     WINPROCESSINFO ** entryHandle;
00741 
00742     // Get a handle to the process.
00743 
00744     HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
00745                                    PROCESS_VM_READ,
00746                                    FALSE, processID );
00747 
00748     // Get the process name.
00749 
00750     if (hProcess)
00751         {
00752         HMODULE hMod;
00753         DWORD cbNeeded;
00754 
00755         if (pEnumProcessModules (hProcess, &hMod, sizeof(hMod), &cbNeeded) )
00756             {
00757             pGetModuleBaseName( hProcess, hMod, szProcessName, 
00758                                sizeof(szProcessName) );
00759             pGetModuleFileNameEx( hProcess, hMod, szProcessPath, 
00760                                sizeof(szProcessPath) );
00761             }
00762         else {
00763             if (processID == 2) { /* This is the System process */
00764                 strcpy (szProcessName, "System.exe");
00765                 strcpy (szProcessPath, "System.exe");
00766                 }
00767             }
00768 
00769         verify (CloseHandle( hProcess ));
00770         }
00771     else {
00772         if (processID == 0) { /* This is the System Idle process */
00773             processID = -2;  /* We alter it so zero is not used */
00774             strcpy (szProcessName, "System Idle Process");
00775             strcpy (szProcessPath, "Idle.exe");
00776             }
00777         }
00778 
00779     entryHandle = addentrytolist (listheader);
00780 
00781     assert (entryHandle);
00782 
00783     lockhandle ((Handle)entryHandle);
00784 
00785     entry = *entryHandle;
00786 
00787     entry->processID = processID;
00788     copyctopstring (szProcessPath, entry->ExeName);
00789     copyctopstring (szProcessName, entry->ModName);
00790 
00791     unlockhandle ((Handle)entryHandle);
00792     } /*AddNTProcessInfo*/
00793 
00794 static boolean enumWinNTProcesses (WINPROCESSHEADER * listheader) {
00795 
00796     // Get the list of process identifiers.
00797 
00798     DWORD aProcesses[1024], cbNeeded, cProcesses;
00799     unsigned int i;
00800     boolean res;
00801 
00802     res = false;
00803 
00804     if (InitToolhelpNT() == false)
00805         return (false);
00806 
00807     releasethreadglobals ();
00808     if (pEnumProcesses (aProcesses, sizeof(aProcesses), &cbNeeded ) ) {
00809 
00810         // Calculate how many process identifiers were returned.
00811 
00812         cProcesses = cbNeeded / sizeof(DWORD);
00813 
00814         // Add processes to list.
00815 
00816         for ( i = 0; i < cProcesses; i++ )
00817             AddNTProcessInfo(listheader, aProcesses[i]);
00818 
00819 
00820         EnumWindows (winHandleEnumProc, (LPARAM)listheader);
00821 
00822         res = true;
00823         }
00824 
00825     grabthreadglobals ();
00826 
00827     return (res);
00828     } /*enumWinNTProcesses*/
00829 
00830 
00831 static boolean enumWin95Processes (WINPROCESSHEADER * listheader) {
00832 
00833     HANDLE snapHandle;
00834     PROCESSENTRY32 pe;
00835 
00836     if (InitToolhelp32() == false)
00837         return (false);
00838 
00839     snapHandle = pCreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);
00840 
00841     if (snapHandle == (HANDLE) -1)
00842         return (false);
00843 
00844     if (snapHandle != NULL) {
00845         pe.dwSize = sizeof(PROCESSENTRY32);
00846 
00847         if (pProcess32First (snapHandle, &pe)) {
00848 
00849             do {
00850                 addprocesstolist (listheader, &pe);
00851                 pe.dwSize = sizeof(PROCESSENTRY32);
00852                 }
00853                 while (pProcess32Next (snapHandle, &pe));
00854 
00855             releasethreadglobals ();
00856         
00857             EnumWindows (winHandleEnumProc, (LPARAM)listheader);
00858             
00859             grabthreadglobals ();
00860 
00861             verify (CloseHandle (snapHandle));
00862             return (true);
00863             }
00864 
00865         verify (CloseHandle (snapHandle));
00866         }
00867 
00868     return (false);
00869     } /*enumWin95Processes*/
00870 
00871 
00872 static boolean enumWinProcesses (WINPROCESSHEADER * listheader) {
00873     OSVERSIONINFO vi;
00874 
00875     listheader->count = 0;
00876     listheader->windowCount = 0;
00877     listheader->head = NULL;
00878 
00879     vi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
00880 
00881     GetVersionEx (&vi);
00882 
00883     if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
00884         listheader->platform = 1;
00885         return (enumWinNTProcesses (listheader));
00886         }
00887 
00888     listheader->platform = 0;
00889     return (enumWin95Processes (listheader));
00890     } /*enumWinProcesses*/
00891 
00892 #endif
00893 
00894 #ifdef MACVERSION
00895 static OSErr getlaunchappparams (const tyfilespec *fsdoc, AppParametersHandle *appparams) {
00896     
00897     /*
00898     2.1a6 dmb: new feature, if bsdoc is the empty string, send ascr/noop event 
00899     instead of aevt/odoc. this should result in no empty document / standard file 
00900     dialog in most apps
00901     */
00902     
00903     AEDesc addrdesc;
00904     AEDesc launchdesc;
00905     AEDescList doclist;
00906     AppleEvent event;
00907     AEEventID eventid;
00908     AEEventClass eventclass;
00909     OSErr errcode;
00910     AliasHandle halias;
00911     AEDesc docdesc;
00912     
00913     if (!haveheapspace (0x0200)) /*512 bytes should be plenty to avoid lots of error checking*/
00914         return (memFullErr);
00915     
00916     if (isemptystring ((*fsdoc).name)) {
00917         
00918         eventclass = 'ascr';
00919         
00920         eventid = 'noop';
00921         
00922         /*
00923         eventid = kAEOpenApplication;
00924         */
00925         }
00926     else {
00927         
00928         eventclass = kCoreEventClass;
00929         
00930         eventid = kAEOpenDocuments;
00931         
00932         errcode = NewAliasMinimal (fsdoc, &halias);
00933         
00934         if (errcode != noErr)
00935             return (errcode);
00936         }
00937     
00938     
00939     #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
00940     
00941         newdescnull (&addrdesc, typeNull);
00942     
00943     #else
00944     
00945         addrdesc.descriptorType = typeNull;
00946     
00947         addrdesc.dataHandle = nil;
00948     
00949     #endif
00950     
00951     AECreateAppleEvent (eventclass, eventid, &addrdesc, kAutoGenerateReturnID, kAnyTransactionID, &event);
00952     
00953     if (eventid == kAEOpenDocuments) { /*need to add document list parameter*/
00954         
00955         AECreateList (nil, 0, false, &doclist); /*create list for the fsspec*/
00956         
00957         //AEPutPtr (&doclist, 0, typeFSS, (Ptr) &fs, sizeof (fs)); /* put filespec on the list%/
00958                 
00959         #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
00960         
00961             newdescwithhandle (&docdesc, typeAlias, (Handle) halias);
00962             
00963         #else
00964         
00965             docdesc.descriptorType = typeAlias;
00966         
00967             docdesc.dataHandle = (Handle) halias;
00968         
00969         #endif
00970         
00971         AEPutDesc (&doclist, 0, &docdesc); /*put alias on the list*/
00972         
00973         AEDisposeDesc (&docdesc);
00974         
00975         AEPutParamDesc (&event, keyDirectObject, &doclist); /*put list on the event*/
00976         
00977         AEDisposeDesc (&doclist); /*dispose list*/
00978         }
00979     
00980     errcode = AECoerceDesc (&event, typeAppParameters, &launchdesc); /*this is what Launch wants*/
00981     
00982     AEDisposeDesc (&event); /*we're done with it*/
00983     
00984     if (errcode != noErr) /*shouldn't fail, but...*/
00985         return (errcode);
00986     
00987     #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
00988         
00989         copydatahandle (&launchdesc, (Handle*) appparams);
00990 
00991     #else
00992     
00993         *appparams = (AppParametersHandle) launchdesc.dataHandle;
00994     
00995     #endif
00996     
00997     return (noErr);
00998     } /*getlaunchappparams*/
00999 #endif
01000 
01001 
01002 #ifdef MACVERSION
01003 static boolean system7apprunning (OSType *, bigstring, typrocessid *);
01004 #endif
01005 
01006 #ifdef MACVERSION
01007 static boolean system7launch (tyfilespec *fsapp, const tyfilespec *fsdoc, boolean flbringtofront) {
01008     
01009     /*
01010     11/10/90 DW: comment out call to MakeFSSpec, the linker can't find it, wire
01011     off routine.
01012     
01013     3/27/91 dmb: re-enabled routine.  no wonder file.launch didn't work!
01014     
01015     12/9/91 dmb: check for oserrors
01016     
01017     3/11/92 dmb: now accept bsdocument and set up launchAppParams
01018     
01019     8/13/92 dmb: test bsdocument for emptyness as well as nil
01020     
01021     9/4/92 dmb: wait for launch to happen
01022     
01023     2002-11-13 AR: Only append ".app" to the filename if there's enough room in the name string
01024     */
01025     
01026     LaunchParamBlockRec sys7lpb;
01027     AppParametersHandle docparams = nil;
01028     OSErr errcode;
01029     long startticks;
01030     
01031     clearbytes (&sys7lpb, longsizeof (sys7lpb));
01032     
01033     #if TARGET_API_MAC_CARBON == 1 /*7.1b19 PBS: append ".app" to the filename if the file can't be found.*/
01034         {
01035         boolean flfolder = false;
01036         
01037         if (!fileexists (fsapp, &flfolder)) {
01038 
01039             unsigned char appext[] = ("\x04" ".app");
01040             const short oldlength = stringlength ((*fsapp).name);
01041             const short newlength = oldlength + stringlength (appext);
01042             const short maxlength = sizeof ((*fsapp).name) - 1; /*minus one for length byte*/
01043             
01044             if (newlength <= maxlength) {
01045 
01046                 pushstring (appext, (*fsapp).name);
01047                             
01048                 if (!fileexists (fsapp, &flfolder)) {
01049 
01050                     setstringlength ((*fsapp).name, oldlength); /*pop off the .app suffix*/
01051 
01052                     } /*if*/
01053                 } /*if*/
01054             } /*if*/
01055         }
01056         /*
01057         {
01058         boolean flfolder = false;
01059         short lenname = (*fsapp).name [0];
01060         
01061         if (!fileexists (fsapp, &flfolder)) {
01062         
01063             (*fsapp).name [0] = (*fsapp).name [0] + 4;
01064             
01065             (*fsapp).name [lenname + 1] = '.';
01066             (*fsapp).name [lenname + 2] = 'a';
01067             (*fsapp).name [lenname + 3] = 'p';
01068             (*fsapp).name [lenname + 4] = 'p';
01069             
01070             if (!fileexists (fsapp, &flfolder)) {
01071             
01072                 (*fsapp).name [0] = lenname; /%pop off the .app suffix%/
01073                 } /%if%/
01074             } /%if%/
01075         }
01076         */
01077     #endif
01078     
01079     sys7lpb.launchAppSpec = (FSSpecPtr) fsapp;
01080     
01081     sys7lpb.launchBlockID = extendedBlock;
01082     
01083     sys7lpb.launchEPBLength = extendedBlockLen;
01084     
01085     sys7lpb.launchControlFlags = launchContinue | launchNoFileFlags;
01086 
01087     if (!flbringtofront)
01088         sys7lpb.launchControlFlags |= launchDontSwitch;
01089     
01090     if (fsdoc != nil) { /*set up docparam with launch event*/
01091         
01092         errcode = getlaunchappparams (fsdoc, &docparams);
01093         
01094         if (oserror (errcode))
01095             return (false);
01096         
01097         setoserrorparam ((ptrstring) (*fsapp).name); /*restore*/
01098         
01099         lockhandle ((Handle) docparams);
01100         
01101         sys7lpb.launchAppParameters = *docparams;
01102         }
01103     
01104     errcode = LaunchApplication (&sys7lpb);
01105     
01106     disposehandle ((Handle) docparams); /*checks for nil*/
01107     
01108     if ((fsdoc != nil) && isemptystring ((*fsdoc).name)) /*sent noop event*/
01109         if (errcode == errAEEventNotHandled)
01110             errcode = noErr;
01111     
01112     if (oserror (errcode))
01113         return (false);
01114     
01115     startticks = gettickcount ();
01116     
01117     while (true) { /*wait for launch to happen*/
01118         
01119         OSType id = 0;
01120         
01121         if (!(*launchcallbacks.waitcallback) ())
01122             return (false);
01123         
01124         if (system7apprunning (&id, (ptrstring) (*fsapp).name, nil))
01125             return (true);
01126         
01127         if (gettickcount () - startticks > maxwait)
01128             return (false);
01129         }
01130     } /*system7launch*/
01131 #endif
01132 
01133 #ifdef flsystem6
01134 
01135 static boolean system6launch (bigstring bsprogram) {
01136     
01137     system6launchparamblock sys6lpb;
01138     bigstring bsname;
01139     bigstring bsfolder;
01140     register OSErr errcode;
01141     WDPBRec wdpb;
01142     CInfoPBRec cipb;
01143     short vnum;
01144     
01145     clearbytes (&sys6lpb, longsizeof (sys6lpb));
01146     
01147     copystring (bsprogram, bsname);
01148     
01149     /*get the volume and directory ids of the path*/
01150     
01151     /*
01152     if (!fileparsevolname (bsprogram, &vnum))
01153         return (false);
01154     */
01155     
01156     folderfrompath (bsprogram, bsfolder);
01157     
01158     cipb.hFileInfo.ioNamePtr = bsfolder;
01159     
01160     cipb.hFileInfo.ioVRefNum = 0; /*vnum;*/
01161     
01162     cipb.hFileInfo.ioFDirIndex = 0;
01163     
01164     errcode = PBGetCatInfo (&cipb, false);
01165     
01166     if (oserror (errcode))
01167         return (false);
01168     
01169     /*now open a working directory there*/
01170     
01171     wdpb.ioNamePtr = bsfolder;
01172     
01173     wdpb.ioVRefNum = 0;
01174     
01175     wdpb.ioWDProcID = 'ERIK';
01176     
01177     wdpb.ioWDDirID = cipb.hFileInfo.ioDirID;
01178     
01179     errcode = PBOpenWD (&wdpb, false);
01180     
01181     if (oserror (errcode))
01182         return (false);
01183     
01184     vnum = wdpb.ioVRefNum;
01185     
01186     filefrompath (bsprogram, bsname);
01187     
01188     sys6lpb.launchFileFlags = cipb.hFileInfo.ioFlFndrInfo.fdFlags;
01189     
01190     /*make the (new) working directory the current one*/
01191     
01192     errcode = SetVol (nil, vnum);
01193     
01194     sys6lpb.name = bsname;
01195     
01196     sys6lpb.launchVRefNum = vnum;
01197     
01198     sys6lpb.launchBlockID = extendedBlock;
01199     
01200     sys6lpb.launchEPBLength = extendedBlockLen;
01201     
01202     sys6lpb.launchControlFlags = 0xC000;
01203     
01204     return (!oserror (LaunchApplication ((LaunchPBPtr) &sys6lpb)));
01205     } /*system6launch*/
01206 
01207 #endif
01208 
01209 #ifdef WIN95VERSION
01210 static boolean systemWinLaunch (const tyfilespec *fsapp, const tyfilespec *fsdoc, boolean flbringtofront) {
01211     char appname[258];
01212     char commandline [514];
01213     STARTUPINFO si;
01214 //  PROCESS_INFORMATION pi;
01215 
01216 
01217     copystring (fsname (fsapp), appname);
01218 
01219     nullterminate (appname);
01220 
01221     if (fsdoc != nil)
01222         copystring (fsname (fsdoc), commandline);
01223     else
01224         setemptystring (commandline);
01225 
01226     nullterminate (commandline);
01227 
01228     si.cb = sizeof(STARTUPINFO);
01229     si.lpReserved = NULL;
01230     si.lpDesktop = NULL;
01231     si.lpTitle = NULL;
01232     si.dwFlags = 0;
01233     si.cbReserved2 = 0;
01234     si.lpReserved2 = NULL;
01235 //  return (CreateProcess (stringbaseaddress (appname), stringbaseaddress (commandline), NULL, NULL, false, CREATE_DEFAULT_ERROR_MODE,
01236 //                  NULL, NULL, &si, &pi));
01237 
01238     return (ShellExecute (NULL, "open", stringbaseaddress (appname), stringbaseaddress (commandline), "", SW_SHOWNORMAL) > (HINSTANCE)32); 
01239     }
01240 #endif
01241 
01242 boolean launchapplication (const tyfilespec *fsapp, const tyfilespec *fsdoc, boolean flbringtofront) {
01243     
01244     setoserrorparam ((ptrstring) fsname(fsapp)); /*in case error message takes a filename parameter*/
01245     
01246 #ifdef MACVERSION
01247     #ifdef flsystem6
01248     
01249     flsystem7 = (gSystemVersion >= 0x0700);
01250     
01251     if (flsystem7)
01252         return (system7launch (bs, bsdocument, flbringtofront));
01253     else
01254         return (system6launch (bs));
01255     
01256     #else
01257     
01258     return (system7launch ((ptrfilespec) fsapp, fsdoc, flbringtofront));
01259     
01260     #endif
01261 #endif
01262     
01263 #ifdef WIN95VERSION
01264     return (systemWinLaunch (fsapp, fsdoc, flbringtofront));
01265 #endif
01266     } /*launchapplication*/
01267 
01268 #ifdef MACVERSION
01269 static boolean visitprocesses (boolean (*visitroutine) (typrocessvisitinfoptr, ProcessInfoRec *), typrocessvisitinfoptr visitinfo) {
01270     
01271     ProcessInfoRec processinfo;
01272     ProcessSerialNumber psn;
01273     bigstring bsname;
01274     FSSpec fss;
01275     
01276     processinfo.processInfoLength = sizeof (processinfo);
01277     
01278     processinfo.processName = bsname; /*place to store process name*/
01279     
01280     processinfo.processAppSpec = &fss; /*place to store process filespec*/
01281     
01282     psn.highLongOfPSN = kNoProcess;
01283     
01284     psn.lowLongOfPSN = kNoProcess;
01285     
01286     while (GetNextProcess (&psn) == noErr) {
01287         
01288         processinfo.processInfoLength = sizeof (ProcessInfoRec);
01289         
01290         if (GetProcessInformation (&psn, &processinfo) != noErr)
01291             continue; /*keep going -- ignore error*/
01292         
01293         if (!(*visitroutine) (visitinfo, &processinfo))
01294             return (false);
01295         }
01296     
01297     return (true);
01298     } /*visitprocesses*/
01299 #endif
01300 
01301 #ifdef MACVERSION
01302 static boolean matchprocess (bigstring bsprocess, ProcessInfoRec *processinfo) {
01303     
01304     /*
01305     9/4/92 dmb: see if bsprocess is the name or full path of the given process
01306     
01307     10/2/92 dmb: if bsprocess is a string4, see if it matches the process id
01308     
01309     7.1b37 PBS: deal with .app extensions on OS X.
01310     */
01311     
01312     bigstring bspath;
01313     OSType id;
01314     
01315     if (stringfindchar (':', bsprocess)) { /*it's a path*/
01316         
01317         if (!filespectopath (processinfo->processAppSpec, bspath))
01318             return (false);
01319         
01320         return (equalidentifiers (bsprocess, bspath));
01321         }
01322     
01323     if (equalidentifiers (bsprocess, processinfo->processName))
01324         return (true);
01325     
01326     #if TARGET_API_MAC_CARBON
01327     
01328         {
01329         bigstring bsprocessminussuffix;
01330         bigstring bssuffix;
01331         
01332         copystring (bsprocess, bsprocessminussuffix);
01333         
01334         if (pullstringsuffix (bsprocessminussuffix, bssuffix, '.')) /*has suffix?*/
01335             
01336             if (equalidentifiers (bssuffix, "\papp")) /*.app suffix?*/
01337             
01338                 if (equalidentifiers (bsprocessminussuffix, processinfo->processName)) /*match?*/
01339                     return (true);
01340         }
01341     
01342     #endif
01343     
01344     if (stringtoostype (bsprocess, &id))
01345         return (id == processinfo->processSignature);
01346     
01347     return (false);
01348     } /*matchprocess*/
01349 #endif
01350 
01351 
01352 #ifdef MACVERSION
01353 static boolean activateprocess (ProcessSerialNumber psn) {
01354     
01355     /*
01356     9/4/92 dmb: check for oserrors & wait for change to happen
01357     
01358     2.1b12 dmb: call the waitcallback at the end of the loop, instead 
01359     of at the beginning. the process may already be in the front.
01360     
01361     2.1b14 dmb: make sure we call the waitcallback before timing out.
01362     
01363     10.0a4 trt/karstenw: avoid -600 (no such process) error in Classic
01364     even if the app is already launched.
01365     */
01366     
01367     long startticks;
01368     
01369 #if defined(TARGET_API_MAC_OS8) && (TARGET_API_MAC_OS8 == 1)
01370     if (oserror (WakeUpProcess (&psn)))
01371         return (false);
01372 #endif
01373     
01374     if (oserror (SetFrontProcess (&psn)))
01375         return (false);
01376     
01377     startticks = gettickcount ();
01378     
01379     while (true) { /*wait for it to happen*/
01380         
01381         ProcessSerialNumber frontpsn;
01382         Boolean flsame;
01383         
01384         if (oserror (GetFrontProcess (&frontpsn)))
01385             break;
01386         
01387         if (oserror (SameProcess (&psn, &frontpsn, &flsame)))
01388             break;
01389         
01390         if (flsame)
01391             break;
01392         
01393         if (!(*launchcallbacks.waitcallback) ())
01394             break;
01395         
01396         if (gettickcount () - startticks > maxwait)
01397             break;
01398         }
01399     
01400     return (true);
01401     } /*activateprocess*/
01402 #endif
01403 
01404 
01405 #ifdef MACVERSION
01406 static boolean processactivatevisit (typrocessvisitinfoptr visitinfo, ProcessInfoRec *processinfo) {
01407     
01408     /*
01409     6/24/92 dmb: make comparison case-insensitive
01410     */
01411     
01412     if (matchprocess (visitinfo->bsprocess, processinfo)) { /*found the process*/
01413         
01414         activateprocess (processinfo->processNumber);
01415         
01416         return (false); /*stop visiting*/
01417         }
01418     
01419     return (true); /*keep visiting*/
01420     } /*processactivatevisit*/
01421 #endif
01422 
01423 
01424 #ifdef MACVERSION
01425 static boolean system7activate (bigstring bsprogram) {
01426     
01427     /*
01428     1/21/93 dmb: if bsprogram is nil, use current process. this is done 
01429     for component support
01430     
01431     2002-11-14 AR: Switch from using globals to a local struct for providing
01432     context to the processactivatevisit callback routine
01433     */
01434     
01435     typrocessvisitinfo info;
01436     
01437     if (bsprogram == nil) {
01438         
01439         ProcessSerialNumber psn;
01440         
01441         GetCurrentProcess (&psn);
01442         
01443         return (activateprocess (psn));
01444         }
01445     
01446     initprocessvisitinfo (&info);
01447     
01448     info.bsprocess = bsprogram; /*set for visit routine*/
01449     
01450     return (!visitprocesses (&processactivatevisit, &info));
01451     } /*system7activate*/
01452 #endif
01453 
01454 
01455 #ifdef MACVERSION
01456 static boolean system6activate (bigstring bsprogram) {
01457 #   if TARGET_API_MAC_CARBON == 1
01458 #       pragma unused (bsprogram)
01459 #   endif
01460 
01461 #   ifdef flsystem6
01462 
01463     bigstring bs;
01464     
01465     if (bsprogram == nil)
01466         return (false);
01467         
01468     filefrompath (bsprogram, bs);
01469         
01470     OpenDeskAcc (bs);
01471     
01472     #endif
01473     
01474     return (true);
01475     } /*system6activate*/
01476 #endif
01477 
01478 boolean activateapplication (bigstring bsprogram) {
01479     
01480     /*
01481     10/3/91 dmb: handle the possibility of bsprogram being a full path
01482 
01483     7.0b33 PBS: Workaround for changes in Win98 and Win2000 -- use AttachThreadInput
01484     to attach the current thread to the foreground window, so that our thread
01485     has permission to set the foreground window.
01486     */
01487     
01488 #ifdef MACVERSION
01489     boolean flsystem7;
01490     
01491     //Code change by Timothy Paustian Friday, June 9, 2000 2:36:02 PM
01492     //Changed because using SysEnvisons and SysEnvRec is like Really old style
01493     //This was changed to Gestalt calls with two new globals see mac.c initmacintosh
01494     
01495     flsystem7 = (gSystemVersion >= 0x0700);
01496     
01497     if (flsystem7)
01498         return (system7activate (bsprogram));
01499     else
01500         return (system6activate (bsprogram));
01501 #endif
01502 
01503 #ifdef WIN95VERSION
01504     WINPROCESSHEADER listheader;
01505     WINPROCESSINFO ** entry;
01506     boolean res;
01507     int currthreadid, winthreadid;
01508     HWND hcurrwnd;
01509 
01510     res = false;
01511 
01512     enumWinProcesses (&listheader);
01513 
01514     if ((bsprogram == NULL) || (stringlength (bsprogram) == 0)) {
01515         entry = getprocessinfofrompid (&listheader, GetCurrentProcessId());
01516         }
01517     else
01518         {
01519         entry = getprocessinfofrommodname (&listheader, bsprogram);
01520 
01521         if (entry == NULL)
01522             entry = getprocessinfofromwintitle (&listheader, bsprogram);
01523 
01524         if (entry == NULL) {
01525             entry = getprocessinfofromexepath (&listheader, bsprogram);
01526             }
01527         }
01528 
01529     if (entry != NULL) {
01530         WINDOWPLACEMENT wp;
01531 
01532         releasethreadglobals();
01533 
01534         wp.length = sizeof(WINDOWPLACEMENT);
01535         if (GetWindowPlacement ((**entry).windowHandle, &wp))
01536             if (wp.showCmd == SW_SHOWMINIMIZED) {
01537                 wp.showCmd = SW_RESTORE;
01538                 SetWindowPlacement ((**entry).windowHandle, &wp);
01539                 }
01540 
01541         currthreadid = GetCurrentThreadId ();
01542 
01543         hcurrwnd = GetForegroundWindow ();
01544    
01545         winthreadid = GetWindowThreadProcessId (hcurrwnd, nil);
01546 
01547         if (currthreadid != winthreadid)
01548 
01549             AttachThreadInput (currthreadid, winthreadid, true);
01550 
01551         res = SetForegroundWindow((**entry).windowHandle);
01552         
01553         if (currthreadid != winthreadid)
01554 
01555             AttachThreadInput (currthreadid, winthreadid, false);
01556 
01557         grabthreadglobals();
01558         }
01559 
01560     cleanProcessHeader (&listheader);
01561     return (res);
01562 #endif
01563     } /*activateapplication*/
01564 
01565 
01566 #ifdef MACVERSION
01567 static boolean processcreatorvisit (typrocessvisitinfoptr visitinfo, ProcessInfoRec *processinfo) {
01568     
01569     if (processinfo->processSignature == visitinfo->idprocess) {
01570         
01571         if (visitinfo->bsprocess != nil)
01572             copystring (processinfo->processName, visitinfo->bsprocess);
01573         
01574         goto match;
01575         }
01576     
01577     if (visitinfo->bsprocess != nil) { /*try to match name*/
01578         
01579         if (matchprocess (visitinfo->bsprocess, processinfo)) {
01580             
01581             visitinfo->idprocess = processinfo->processSignature;
01582             
01583             goto match;
01584             }
01585         }
01586     
01587     return (true); /*keep visiting*/
01588     
01589     match: {
01590     
01591         if (visitinfo->psnprocess != nil) {
01592             
01593             visitinfo->psnprocess->highLongOfPSN = processinfo->processNumber.highLongOfPSN;
01594             
01595             visitinfo->psnprocess->lowLongOfPSN = processinfo->processNumber.lowLongOfPSN;
01596             }
01597         
01598         return (false); /*stop visiting*/
01599         }
01600     } /*processcreatorvisit*/
01601 #endif
01602 
01603 
01604 
01605 #ifdef MACVERSION
01606 static boolean system7apprunning (OSType *idapp, bigstring appname, typrocessid *psn) {
01607 
01608     /*
01609     2002-11-14 AR: Switch from using globals to a local struct for providing
01610     context to the processcreatorvisit callback routine
01611     */
01612     
01613     typrocessvisitinfo info;
01614     
01615     initprocessvisitinfo (&info);
01616         
01617     info.idprocess = *idapp; /*set for visit routine*/
01618     
01619     info.bsprocess = appname;
01620     
01621     info.psnprocess = psn;
01622     
01623     if (visitprocesses (&processcreatorvisit, &info))
01624         return (false);
01625     
01626     *idapp = info.idprocess;
01627     
01628     return (true);
01629     } /*system7apprunning*/
01630 #endif
01631 
01632 
01633 #ifdef flsystem6
01634 
01635 static boolean system6apprunning (OSType *appid, bigstring appname) {
01636     
01637     ostypetostring (*appid, appname); /*better than nothing*/
01638     
01639     return (true);
01640     } /*system6apprunning*/
01641 
01642 #endif
01643 
01644 boolean findrunningapplication (OSType *appid, bigstring appname, typrocessid *psn) {
01645     
01646 #ifdef MACVERSION
01647     /*
01648     this is really a system7-only routine.  under system 6, we always return true.
01649     
01650     under system 7, we look for an application with the given id, and return 
01651     true if we find it, filling in appname.
01652     
01653     2.1a7 dmb: take psn param
01654     */
01655     
01656     #ifdef flsystem6
01657     
01658     boolean flsystem7;
01659     
01660     flsystem7 = (macworld.systemVersion >= 0x0700);
01661     
01662     if (!flsystem7)
01663         return (system6apprunning (appid, appname));
01664     else
01665     
01666     #endif
01667     
01668         return (system7apprunning (appid, appname, psn));
01669 #endif
01670 
01671 #ifdef WIN95VERSION
01672     WINPROCESSHEADER listheader;
01673     WINPROCESSINFO ** entry;
01674     boolean res;
01675 
01676     res = false;
01677 
01678     enumWinProcesses (&listheader);
01679 
01680     entry = getprocessinfofrommodname (&listheader, appname);
01681 
01682     if (entry == NULL)
01683         entry = getprocessinfofromwintitle (&listheader, appname);
01684 
01685     if (entry == NULL) {
01686         entry = getprocessinfofromexepath (&listheader, appname);
01687         }
01688 
01689     if (entry != NULL) {
01690         res = true;
01691         }
01692 
01693     cleanProcessHeader (&listheader);
01694     return (res);
01695 #pragma message ("WIN95 findrunningapplication does not handle appid")
01696 #endif
01697     } /*findrunningapplication*/
01698 
01699 
01700 #ifdef MACVERSION
01701 static boolean system7frontprogram (bigstring bsprogram, boolean flfullpath) {
01702     
01703     /*
01704     10/3/91 dmb: if flfullpath is true, return the full path instead of the 
01705     process name
01706     */
01707     
01708     ProcessInfoRec processinfo;
01709     ProcessSerialNumber psn;
01710     FSSpec fs;
01711     
01712     processinfo.processInfoLength = sizeof (processinfo);
01713     
01714     processinfo.processName = bsprogram; /*place to store process name*/
01715     
01716     processinfo.processAppSpec = &fs;
01717     
01718     if (oserror (GetFrontProcess (&psn)))
01719         return (false);
01720     
01721     if (oserror (GetProcessInformation (&psn, &processinfo)))
01722         return (false);
01723     
01724     if (flfullpath)
01725         filespectopath (&fs, bsprogram);
01726     
01727     return (true);
01728     } /*system7frontprogram*/
01729 #endif
01730 
01731 
01732 #ifdef  flsystem6
01733 
01734 static boolean system6frontprogram (bigstring bsprogram) {
01735     
01736     copystring ((ptrstring) CurApName, bsprogram);
01737     
01738     return (true);
01739     } /*system6frontprogram*/
01740 
01741 #endif
01742 
01743 
01744 boolean getfrontapplication (bigstring bsprogram, boolean flfullpath) {
01745 
01746 #ifdef MACVERSION   
01747     #ifdef flsystem6
01748     
01749         boolean flsystem7;
01750         
01751         flsystem7 = (macworld.systemVersion >= 0x0700);
01752         
01753         if (flsystem7)
01754             return (system7frontprogram (bsprogram, flfullpath));
01755         else
01756             return (system6frontprogram (bsprogram));
01757     
01758     #else
01759     
01760         return (system7frontprogram (bsprogram, flfullpath));
01761     
01762     #endif
01763 #endif
01764 
01765 #ifdef WIN95VERSION
01766     WINPROCESSHEADER listheader;
01767     WINPROCESSINFO ** entry;
01768     boolean res;
01769     DWORD pid;
01770 
01771     res = false;
01772 
01773     enumWinProcesses (&listheader);
01774 
01775     GetWindowThreadProcessId (GetForegroundWindow(), &pid);
01776 
01777     entry = getprocessinfofrompid (&listheader, pid);
01778 
01779     if (entry != NULL) {
01780         if (flfullpath) {
01781             copystring ((**entry).ExeName, bsprogram);
01782             }
01783         else
01784             {
01785             copystring ((**entry).ModName, bsprogram);
01786             }
01787 
01788         res = true;
01789         }
01790 
01791     cleanProcessHeader (&listheader);
01792     return (res);
01793 #endif
01794     } /*getfrontapplication*/
01795 
01796 
01797 #ifdef MACVERSION
01798 static boolean processcountvisit (typrocessvisitinfoptr visitinfo, ProcessInfoRec *processinfo) {
01799     
01800     visitinfo->ctprocesses++;
01801     
01802     if (visitinfo->ctprocesses == visitinfo->nthprocess) { /*found the one we're looking for*/
01803         
01804         copystring (processinfo->processName, visitinfo->bsprocess);
01805         
01806         return (false); /*stop visiting*/
01807         }
01808     
01809     return (true); /*keep visiting*/
01810     } /*processcountvisit*/
01811 #endif
01812 
01813 
01814 short countapplications (void) {
01815 
01816     /*
01817     2002-11-14 AR: Switch from using globals to a local struct for providing
01818     context to the processcountvisit callback routine
01819     */
01820         
01821 #ifdef MACVERSION
01822     typrocessvisitinfo info;
01823     boolean flsystem7;
01824     //Code change by Timothy Paustian Friday, June 9, 2000 2:36:02 PM
01825     //Changed because using SysEnvisons and SysEnvRec is like Really old style
01826     //This was changed to Gestalt calls with two new globals see mac.c initmacintosh
01827     flsystem7 = (gSystemVersion >= 0x0700);
01828     
01829     if (!flsystem7)
01830         return (0);
01831     
01832     initprocessvisitinfo (&info);
01833     
01834     info.ctprocesses = 0; /*set for visit routine*/
01835     
01836     info.nthprocess = -1; /*so we'll never find a match*/
01837     
01838     visitprocesses (&processcountvisit, &info);
01839     
01840     return (info.ctprocesses);
01841 #endif
01842 
01843 #ifdef WIN95VERSION
01844     WINPROCESSHEADER listheader;
01845     short count;
01846 
01847     enumWinProcesses (&listheader);
01848 
01849     count = (short)listheader.count;
01850 
01851     cleanProcessHeader (&listheader);
01852     return (count);
01853 #endif
01854     } /*countapplications*/
01855 
01856 
01857 boolean getnthapplication (short n, bigstring bsprogram) {
01858     
01859     /*
01860     2002-11-14 AR: Switch from using globals to a local struct for providing
01861     context to the processcountvisit callback routine
01862     */
01863     
01864 #ifdef MACVERSION
01865     typrocessvisitinfo info;
01866     boolean flsystem7;
01867     //Code change by Timothy Paustian Friday, June 9, 2000 2:36:02 PM
01868     //Changed because using SysEnvisons and SysEnvRec is like Really old style
01869     //This was changed to Gestalt calls with two new globals see mac.c initmacintosh
01870     flsystem7 = (gSystemVersion >= 0x0700);
01871     
01872     if (!flsystem7)
01873         return (false);
01874     
01875     initprocessvisitinfo (&info);
01876     
01877     info.ctprocesses = 0; /*set for visit routine*/
01878     
01879     info.nthprocess = n; /*the one we want*/
01880     
01881     info.bsprocess = bsprogram; /*point to caller's storage*/
01882     
01883     return (!visitprocesses (&processcountvisit, &info));
01884 #endif
01885 
01886 #ifdef WIN95VERSION
01887     WINPROCESSHEADER listheader;
01888     WINPROCESSINFO ** entry;
01889     boolean res;
01890 
01891     res = false;
01892 
01893     enumWinProcesses (&listheader);
01894 
01895     entry = listheader.head;
01896 
01897     while ((n > 1) && (entry != NULL)) {
01898         entry = (**entry).next;
01899         --n;
01900         }
01901 
01902     setstringlength (bsprogram, 0);
01903 
01904     if (entry != NULL) {
01905         copystring ((**entry).ModName, bsprogram);
01906 
01907         if (stringlength(bsprogram) == 0)
01908             copystring ((**entry).ExeName, bsprogram);
01909 
01910         res = true;
01911         }
01912 
01913     cleanProcessHeader (&listheader);
01914     return (res);
01915 #endif
01916     } /*getnthapplication*/
01917 
01918 
01919 #ifdef MACVERSION
01920 static boolean getprocesspathvisit (typrocessvisitinfoptr visitinfo, ProcessInfoRec *processinfo) {
01921     
01922     /*
01923     7/14/92 dmb: created
01924     */
01925     
01926     if (matchprocess (visitinfo->bsprocess, processinfo)) { /*found the process*/
01927         
01928         *(visitinfo->fsprocess) = *(processinfo->processAppSpec);
01929         
01930         return (false); /*stop visiting*/
01931         }
01932     
01933     return (true); /*keep visiting*/
01934     } /*getprocesspathvisit*/
01935 #endif
01936 
01937 
01938 boolean getapplicationfilespec (bigstring bsprogram, tyfilespec *fs) {
01939     
01940     /*
01941     5.0.2b21 dmb: clear unused fields on Win
01942     
01943     2000-06-09 Timothy Paustian: Changed because using SysEnvisons
01944     and SysEnvRec is like Really old style. This was changed to Gestalt calls
01945     with two new globals see mac.c initmacintosh.
01946     
01947     2002-11-14 AR: Switch from using globals to a local struct for providing
01948     context to the getprocesspathvisit callback routine
01949     
01950     2004-10-26 aradke: New Carbon/Mach-O implementation for obtaining
01951     a filespec to our application bundle, i.e. the Frontier.app "folder".
01952     
01953     2006-02-17 aradke: Clear filespec before doing our thing on Mac too,
01954     so the caller won't crash if he ignores a false return value and
01955     tries to access the filespec anyway. Our only caller with a non-nil
01956     bsprogram currently is sys.getAppPath (shellsysverbs.c) and it does
01957     exactly that.
01958     */
01959 
01960 #ifdef MACVERSION
01961     typrocessvisitinfo info;
01962     boolean flsystem7;
01963     
01964     clearbytes (fs, sizeof (*fs));  /* 2006-02-17 aradke */
01965 
01966     flsystem7 = (gSystemVersion >= 0x0700);
01967     
01968     if (!flsystem7)
01969         return (false);
01970     
01971     if (bsprogram == nil) { /*get path to this process*/
01972         
01973         #if TARGET_RT_MAC_MACHO
01974             CFBundleRef mybundleref;
01975             CFURLRef myurlref;
01976             FSRef myfsref;
01977             boolean res;
01978             OSErr err;
01979             
01980             mybundleref = CFBundleGetMainBundle();
01981             
01982             if (mybundleref == NULL)
01983                 return (false);
01984             
01985             myurlref = CFBundleCopyBundleURL(mybundleref);
01986             
01987             if (myurlref == NULL)
01988                 return (false);
01989 
01990             res = CFURLGetFSRef(myurlref, &myfsref);
01991             
01992             CFRelease(myurlref);
01993             
01994             if (!res)
01995                 return (false);
01996             
01997             err = FSGetCatalogInfo(&myfsref, kFSCatInfoNone, NULL, NULL, fs, NULL);
01998             
01999             return (err == noErr);
02000         #else
02001             ProcessInfoRec processinfo;
02002             ProcessSerialNumber psn;
02003             
02004             processinfo.processInfoLength = sizeof (processinfo);
02005             
02006             processinfo.processName = nil; /*place to store process name*/
02007             
02008             processinfo.processAppSpec = fs; /*place to store process filespec*/
02009             
02010             psn.highLongOfPSN = 0;
02011             
02012             psn.lowLongOfPSN = kCurrentProcess;
02013             
02014             if (GetProcessInformation (&psn, &processinfo) != noErr)
02015                 return (false);
02016             
02017             return (true);
02018         #endif
02019         }
02020     
02021     initprocessvisitinfo (&info);
02022     
02023     info.bsprocess = bsprogram; /*point to caller's storage*/
02024     
02025     info.fsprocess = fs; /*can be same storage as bsprogram -- or not*/
02026     
02027     return (!visitprocesses (&getprocesspathvisit, &info));
02028 #endif
02029 
02030 #ifdef WIN95VERSION
02031     WINPROCESSHEADER listheader;
02032     WINPROCESSINFO ** entry;
02033     boolean res;
02034     char curpath[256];
02035     short len;
02036 //  OSVERSIONINFO osinfo;
02037 
02038 //  osinfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
02039 
02040 //  GetVersionEx (&osinfo);
02041 
02042 //  if (osinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
02043 
02044     res = false;
02045     
02046     clearbytes (fs, sizeof (*fs));
02047 
02048     if ((bsprogram == NULL) || (stringlength (bsprogram) == 0)) {
02049 
02050         len = (short)GetModuleFileName (NULL, curpath, sizeof(curpath));
02051 
02052         if (len > 0) {
02053             curpath[len] = 0;  //ensure null termination
02054             copyctopstring (curpath, fsname(fs));
02055             res = true;
02056             return (res);
02057             }
02058         }
02059 
02060 
02061     enumWinProcesses (&listheader);
02062 
02063     if ((bsprogram == NULL) || (stringlength (bsprogram) == 0)) {
02064         entry = getprocessinfofrompid (&listheader, GetCurrentProcessId());
02065         }
02066     else
02067         {
02068         entry = getprocessinfofrommodname (&listheader, bsprogram);
02069 
02070         if (entry == NULL)
02071             entry = getprocessinfofromwintitle (&listheader, bsprogram);
02072 
02073         if (entry == NULL)
02074             entry = getprocessinfofromexepath (&listheader, bsprogram);
02075         }
02076 
02077     setstringlength (fsname(fs), 0);
02078 
02079     if (entry != NULL) {
02080         copystring ((**entry).ExeName, fsname(fs));
02081         res = true;
02082         }
02083 //  else {
02084 //      GetCurrentDirectory (256, curpath);
02085 //      strcat (curpath, "\\Frontier.exe");
02086 //      copyctopstring (curpath, fsname(fs));
02087 //      res = true;
02088 //      }
02089 
02090     cleanProcessHeader (&listheader);
02091     return (res);
02092 #endif
02093     } /*getapplicationfilespec*/
02094 
02095 
02096 boolean executeresource (ResType type, short id, bigstring bsname) {
02097     
02098 #ifdef MACVERSION
02099     /*
02100     if bsname is nil, get the resource by id; otherwise, ignore the id.
02101     
02102     this may not belong in this file, but running an external resource is 
02103     somewhat analagous to launching a program, so....
02104     
02105     3.0.4 dmb: void prototype for 68K direct call
02106     */
02107     
02108     Handle hcode;
02109     
02110     if (bsname == nil)
02111         hcode = GetResource (type, id);
02112     else
02113         hcode = GetNamedResource (type, bsname);
02114     
02115     if (hcode == nil)
02116         return (false);
02117     
02118     lockhandle (hcode);
02119     
02120     #if THINK_C
02121     
02122     CallPascal (*hcode);
02123     
02124     //Code change by Timothy Paustian Sunday, May 7, 2000 11:18:54 PM
02125     //we can just call the routine directly. I think.
02126     #elif TARGET_RT_MAC_CFM
02127     
02128     #if TARGET_API_MAC_CARBON == 1
02129         (*(pascal void (*) (void)) hcode) ();
02130     #else
02131     {
02132         UniversalProcPtr upp = NewRoutineDescriptor ((ProcPtr) *hcode, kPascalStackBased, kM68kISA);
02133         
02134         CallUniversalProc (upp, kPascalStackBased);
02135         
02136         DisposeRoutineDescriptor (upp);
02137     }
02138     #endif
02139         
02140     #else
02141     
02142         (*(pascal void (*) (void)) hcode) ();
02143     
02144     #endif
02145     
02146     unlockhandle (hcode);
02147     
02148     ReleaseResource (hcode);
02149     
02150     return (true);
02151 #endif
02152 
02153 #ifdef WIN95VERSION
02154     /* not supported */
02155     return (false);
02156 #endif
02157     } /*executeresource*/
02158 
02159 
02160 #ifdef MACVERSION
02161 OSType getprocesscreator (void) {
02162     
02163     /*
02164     get the 4-character creator identifier for the application we're running 
02165     inside of.
02166     */
02167     
02168     ProcessSerialNumber psn;
02169     ProcessInfoRec info;
02170     
02171     GetCurrentProcess (&psn);
02172     
02173     info.processInfoLength = (long) sizeof (info);
02174     
02175     info.processName = nil;
02176     
02177     info.processAppSpec = nil;
02178     
02179     GetProcessInformation (&psn, &info);
02180     
02181     return (info.processSignature);
02182     } /*getprocesscreator*/
02183 #endif
02184 
02185 
02186 typrocessid getcurrentprocessid (void) {
02187     
02188     ProcessSerialNumber psn;
02189     
02190 #ifdef MACVERSION
02191     GetCurrentProcess (&psn);
02192 #endif
02193 
02194 #ifdef WIN95VERSION
02195     psn = GetCurrentProcessId();
02196 #endif
02197     
02198     return (psn);
02199     } /*getcurrentprocessid*/
02200 
02201 
02202 boolean iscurrentapplication (typrocessid psn) {
02203     
02204     ProcessSerialNumber currentpsn;
02205     
02206 #ifdef MACVERSION
02207     Boolean flsame;
02208     OSErr err;
02209 
02210     GetCurrentProcess (&currentpsn);
02211 
02212     err = SameProcess (&psn, &currentpsn, &flsame);
02213     
02214     return ((err == noErr) && flsame);
02215 #endif
02216     
02217 #ifdef WIN95VERSION
02218     currentpsn = GetCurrentProcessId();
02219 
02220     return (currentpsn == psn);
02221 #endif
02222     } /*iscurrentapplication*/
02223 
02224 boolean isfrontapplication (typrocessid psn) {
02225 
02226 #ifdef MACVERSION
02227     ProcessSerialNumber frontpsn;
02228     Boolean flsame;
02229     OSErr err;
02230     
02231     GetFrontProcess (&frontpsn);
02232     
02233     err = SameProcess (&psn, &frontpsn, &flsame);
02234     
02235     return ((err == noErr) && flsame);
02236 #endif
02237 
02238 #ifdef WIN95VERSION
02239     WINPROCESSHEADER listheader;
02240     WINPROCESSINFO ** entry;
02241     boolean res;
02242     DWORD pid;
02243 
02244     res = false;
02245 
02246     enumWinProcesses (&listheader);
02247 
02248     entry = getprocessinfofrompid (&listheader, psn);
02249 
02250     if (entry != NULL) {
02251         GetWindowThreadProcessId (GetForegroundWindow(), &pid);
02252 
02253         if ((**entry).processID == pid)
02254             res = true;
02255         }
02256 
02257     cleanProcessHeader (&listheader);
02258     return (res);
02259 #endif
02260     } /*isfrontapplication*/
02261 
02262 
02263 #ifdef MACVERSION
02264 boolean activateapplicationwindow (typrocessid psn, WindowPtr w) {
02265     
02266     /*
02267     4/20/93 dmb: activate the application and ask it to select window w.
02268     
02269     the event we send corresponds to the handler installed by the window 
02270     sharing server (us).
02271     */
02272     
02273     AEDesc addrdesc;
02274     AppleEvent event, reply;
02275     OSErr err;
02276     register hdllandglobals hlg;
02277     
02278     err = AECreateDesc (typeProcessSerialNumber, (Ptr) &psn, longsizeof (psn), &addrdesc);
02279     
02280     err = AECreateAppleEvent ('SHUI', 'selw', &addrdesc, kAutoGenerateReturnID, kAnyTransactionID, &event);
02281     
02282     AEDisposeDesc (&addrdesc);
02283     
02284     err = AEPutParamPtr (&event, '----', typeLongInteger, (Ptr) &w, sizeof (long));
02285     
02286     hlg = landgetglobals ();
02287     
02288     err = (*(**hlg).eventsendcallback) (&event, &reply, 
02289         
02290         (AESendMode) kAEWaitReply + kAEAlwaysInteract + kAECanSwitchLayer, (AESendPriority) kAEHighPriority, 60L, nil, nil);
02291     
02292     err = WakeUpProcess (&psn);
02293     
02294     err = SetFrontProcess (&psn);
02295     
02296     return (true); /***/
02297     } /*activateapplicationwindow*/
02298 #endif
02299 
02300 /* above not supported for MS Windows */
02301 
02302 
02303 

Generated on Wed May 31 18:19:54 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6