Exemple #1
1
BOOL InitApp (LPSTR pszCmdLineA)
{
   BOOL fShow = FALSE;
   BOOL fQuiet = FALSE;
   BOOL fExit = FALSE;
   BOOL fInstall = FALSE;
   BOOL fUninstall = FALSE;
   BOOL fAutoInit = FALSE;
   BOOL fNetDetect = FALSE;
   BOOL fRenewMaps = FALSE;

   // Initialize our global variables and window classes
   //
   memset (&g, 0x00, sizeof(g));
   g.fStartup = TRUE;

   // Parse the command-line
   //
   while (pszCmdLineA && *pszCmdLineA)
      {
      if ((*pszCmdLineA != '-') && (*pszCmdLineA != '/'))
         break;

      switch (*(++pszCmdLineA))
         {
         case 'a':
         case 'A':
            fAutoInit = TRUE;
            break;

         case 'm':
         case 'M':
            fRenewMaps = TRUE;
            break;

         case 'n':
         case 'N':
            fNetDetect = TRUE;
            break;

         case 's':
         case 'S':
            fShow = TRUE;
            break;

         case 'q':
         case 'Q':
            fQuiet = TRUE;
            break;

         case 'e':
         case 'E':
            fExit = TRUE;
            break;

         case 'i':
         case 'I':
            fInstall = TRUE;
            break;

         case 'u':
         case 'U':
            fUninstall = TRUE;
            break;

         case ':':
             CopyAnsiToString(g.SmbName,pszCmdLineA);
			 MapShareName(pszCmdLineA);
			 break;

         case 'z':
         case 'Z':
             DoUnMapShare(TRUE);
             return(0);

         case 'x':
         case 'X':
             TestAndDoMapShare(SERVICE_START_PENDING);
             TestAndDoMapShare(SERVICE_RUNNING);
             return 0;
         }

      while (*pszCmdLineA && (*pszCmdLineA != ' '))
         ++pszCmdLineA;
	  if (*pszCmdLineA==' ') ++pszCmdLineA;
      }

   if (fInstall)
      Shortcut_FixStartup (cszSHORTCUT_NAME, g.fStartup = TRUE);
   else if (fUninstall)
      Shortcut_FixStartup (cszSHORTCUT_NAME, g.fStartup = FALSE);

   if (fInstall || fUninstall)
      {
      HKEY hk;
      if (RegCreateKeyEx (HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY, 0, NULL, 0,
                         (IsWow64()?KEY_WOW64_64KEY:0)|KEY_WRITE, NULL, &hk, NULL) == 0)
         {
         DWORD dwSize = sizeof(g.fStartup);
         DWORD dwType = REG_DWORD;
         RegSetValueEx (hk, TEXT("ShowTrayIcon"), NULL, dwType, (PBYTE)&g.fStartup, dwSize);
         RegCloseKey (hk);
         }
      }

   // Only show up if there's not another version of this app around already.
   //
   for (HWND hSearch = GetWindow (GetDesktopWindow(), GW_CHILD);
        hSearch && IsWindow(hSearch);
        hSearch = GetWindow (hSearch, GW_HWNDNEXT))
      {
      TCHAR szClassName[ cchRESOURCE ];
      if (GetClassName (hSearch, szClassName, cchRESOURCE))
         {
         if (!lstrcmpi (szClassName, cszCLASSNAME))
            {
            if (fShow)
               PostMessage (hSearch, WM_COMMAND, M_ACTIVATE, 0);
            else if (fExit)
               PostMessage (hSearch, WM_COMMAND, M_TERMINATE_NOW, 0);
            else if (fUninstall)
               PostMessage (hSearch, WM_COMMAND, M_TERMINATE_NOW, 0);
            return FALSE;
            }
         }
      }

   if (fExit || fUninstall || fInstall)
      return FALSE;

   HKEY hk;
    if (RegOpenKeyEx (HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY, 0,
                       (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &hk) == 0)
    {
        DWORD dwSize = sizeof(g.fStartup);
        DWORD dwType = REG_DWORD;
        RegQueryValueEx (hk, TEXT("ShowTrayIcon"), NULL, &dwType, (PBYTE)&g.fStartup, &dwSize);
        RegCloseKey (hk);
    }
    else if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY, 0,
                            (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &hk) == 0)
      {
      DWORD dwSize = sizeof(g.fStartup);
      DWORD dwType = REG_DWORD;
      RegQueryValueEx (hk, TEXT("ShowTrayIcon"), NULL, &dwType, (PBYTE)&g.fStartup, &dwSize);
      RegCloseKey (hk);
      }

   Shortcut_FixStartup (cszSHORTCUT_NAME, g.fStartup);

   // Is this Windows NT?
   //
   OSVERSIONINFO Version;
   memset (&Version, 0x00, sizeof(Version));
   Version.dwOSVersionInfoSize = sizeof(Version);
   if (GetVersionEx (&Version))
      g.fIsWinNT = (Version.dwPlatformId == VER_PLATFORM_WIN32_NT) ? TRUE : FALSE;

   if (!g.fIsWinNT)
      lstrcpy (g.szHelpFile, TEXT("afs-light.hlp"));
   else
      lstrcpy (g.szHelpFile, TEXT("afs-nt.hlp"));

   // Initialize winsock etc
   //
   WSADATA Data;
   WSAStartup (0x0101, &Data);

   InitCommonControls();
   RegisterCheckListClass();
   osi_Init();
   lock_InitializeMutex(&g.expirationCheckLock, "expiration check lock", 0);
   lock_InitializeMutex(&g.credsLock, "global creds lock", 0);

   KFW_AFS_wait_for_service_start();

   if ( IsDebuggerPresent() ) {
       if ( !g.fIsWinNT )
           OutputDebugString("No Service Present on non-NT systems\n");
       else {
           if ( IsServiceRunning() )
               OutputDebugString("AFSD Service started\n");
           else {
               OutputDebugString("AFSD Service stopped\n");
               if ( !IsServiceConfigured() )
                   OutputDebugString("AFSD Service not configured\n");
               else if ( fAutoInit )
                   OutputDebugString("AFSD Service will be started\n");
           }
       }
   }

    // If the service isn't started yet, and autoInit start the service
    if ( g.fIsWinNT && !IsServiceRunning() && IsServiceConfigured() && fAutoInit ) {
        SC_HANDLE hManager;

        if ((hManager = OpenSCManager( NULL, NULL,
                                       SC_MANAGER_CONNECT |
                                       SC_MANAGER_ENUMERATE_SERVICE |
                                       SC_MANAGER_QUERY_LOCK_STATUS)) != NULL )
        {
            SC_HANDLE hService;
            if ((hService = OpenService( hManager, TEXT("TransarcAFSDaemon"),
                                         SERVICE_QUERY_STATUS | SERVICE_START) ) != NULL)
            {
                if (StartService(hService, 0, 0)) {
                    if ( IsDebuggerPresent() )
                        OutputDebugString("AFSD Service start successful\n");
                    fRenewMaps = TRUE;
                } else if ( IsDebuggerPresent() )
                    OutputDebugString("AFSD Service start failed\n");

                CloseServiceHandle (hService);
            }

            CloseServiceHandle (hManager);
        }
        KFW_AFS_wait_for_service_start();
    }

    KFW_initialize();

   // Create a main window. All further initialization will be done during
   // processing of WM_INITDIALOG.
   //
   WNDCLASS wc;
   if (!GetClassInfo (NULL, WC_DIALOG, &wc))   // Get dialog class info
      return FALSE;
   wc.hInstance = THIS_HINST;
   wc.hIcon = TaLocale_LoadIcon (IDI_MAIN);
   wc.lpszClassName = cszCLASSNAME;
   wc.style |= CS_GLOBALCLASS;
   RegisterClass(&wc);

   g.hMain = ModelessDialog (IDD_MAIN, NULL, (DLGPROC)Main_DlgProc);
   if (g.hMain == NULL)
      return FALSE;

   // If the service isn't started yet, show our startup wizard.
   //
   if (!IsServiceRunning() && !fQuiet)
      {
      if (!g.fIsWinNT)
         Message (MB_ICONHAND, IDS_UNCONFIG_TITLE_95, IDS_UNCONFIG_DESC_95);
      else if (IsServiceConfigured())
         ShowStartupWizard();
      else if (!IsServerInstalled())
         Message (MB_ICONHAND, IDS_UNCONFIG_TITLE, IDS_UNCONFIG_DESC);
      }
   if (IsServiceRunning()) {
      if ( fRenewMaps )
      {
          if ( IsDebuggerPresent() )
              OutputDebugString("Renewing Drive Maps\n");
          DoMapShareChange(FALSE);
      }
      if (fShow)
      {
      if ( IsDebuggerPresent() )
          OutputDebugString("Displaying Main window\n");
      Main_Show (TRUE);
      }
      // If the root cell is reachable and we have no tokens
      // display the Obtain Tokens dialog to the user
      if ( fAutoInit ) {
          if ( IsDebuggerPresent() )
              OutputDebugString("Obtaining Tokens (if needed)\n");
          ObtainTokensFromUserIfNeeded(g.hMain);
      }
   } else if ( IsDebuggerPresent() )
       OutputDebugString("AFSD Service Stopped\n");

    if ( fNetDetect ) {
        // Start IP Address Change Monitor
        if ( IsDebuggerPresent() )
            OutputDebugString("Activating Network Change Monitor\n");
        IpAddrChangeMonitorInit(g.hMain);
    }
    Main_EnableRemindTimer(TRUE);
    return TRUE;
}
Exemple #2
0
void cm_InitCell(int newFile, long maxCells)
{
    static osi_once_t once;

    if (osi_Once(&once)) {
        cm_cell_t * cellp;

        lock_InitializeRWLock(&cm_cellLock, "cell global lock", LOCK_HIERARCHY_CELL_GLOBAL);

        if ( newFile ) {
            cm_data.allCellsp = NULL;
            cm_data.currentCells = 0;
            cm_data.maxCells = maxCells;
            memset(cm_data.cellNameHashTablep, 0, sizeof(cm_cell_t *) * cm_data.cellHashTableSize);
            memset(cm_data.cellIDHashTablep, 0, sizeof(cm_cell_t *) * cm_data.cellHashTableSize);

#ifdef AFS_FREELANCE_CLIENT
            /* Generate a dummy entry for the Freelance cell whether or not
             * freelance mode is being used in this session
             */

            cellp = &cm_data.cellBaseAddress[cm_data.currentCells++];
            memset(cellp, 0, sizeof(cm_cell_t));
            cellp->magic = CM_CELL_MAGIC;

            lock_InitializeMutex(&cellp->mx, "cm_cell_t mutex", LOCK_HIERARCHY_CELL);

            lock_ObtainMutex(&cellp->mx);
            lock_ObtainWrite(&cm_cellLock);

            /* copy in name */
            strncpy(cellp->name, "Freelance.Local.Cell", CELL_MAXNAMELEN); /*safe*/
            cellp->name[CELL_MAXNAMELEN-1] = '\0';

            /* thread on global list */
            cellp->allNextp = cm_data.allCellsp;
            cm_data.allCellsp = cellp;

            cellp->cellID = AFS_FAKE_ROOT_CELL_ID;
            cellp->vlServersp = NULL;
            _InterlockedOr(&cellp->flags, CM_CELLFLAG_FREELANCE);

            cm_AddCellToNameHashTable(cellp);
            cm_AddCellToIDHashTable(cellp);
            lock_ReleaseWrite(&cm_cellLock);
            lock_ReleaseMutex(&cellp->mx);
#endif
        } else {
            lock_ObtainRead(&cm_cellLock);
            for (cellp = cm_data.allCellsp; cellp; cellp=cellp->allNextp) {
                lock_InitializeMutex(&cellp->mx, "cm_cell_t mutex", LOCK_HIERARCHY_CELL);
                cellp->vlServersp = NULL;
                _InterlockedOr(&cellp->flags, CM_CELLFLAG_VLSERVER_INVALID);
            }
            lock_ReleaseRead(&cm_cellLock);
        }

        osi_EndOnce(&once);
    }
}
Exemple #3
0
long RpcInit()
{
    LONG status = ERROR_SUCCESS;
    HANDLE listenThread;
    ULONG listenThreadID = 0;
    char * name = "afsd_rpc_ShutdownEvent";

    lock_InitializeMutex(&tokenEventLock, "token event lock",
                          LOCK_HIERARCHY_TOKEN_EVENT_GLOBAL);

    rpc_ShutdownEvent = thrd_CreateEvent(NULL, FALSE, FALSE, name);
    if ( GetLastError() == ERROR_ALREADY_EXISTS )
        afsi_log("Event Object Already Exists: %s", name);

    listenThread = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)RpcListen,
                                0, 0, &listenThreadID);

    if (listenThread == NULL) {
        status = GetLastError();
    }
    CloseHandle(listenThread);

    return status;
}
Exemple #4
0
cm_cell_t *cm_GetCell_Gen(char *namep, char *newnamep, afs_uint32 flags)
{
    cm_cell_t *cp, *cp2;
    long code;
    char fullname[CELL_MAXNAMELEN]="";
    char linkedName[CELL_MAXNAMELEN]="";
    char name[CELL_MAXNAMELEN]="";
    int  hasWriteLock = 0;
    int  hasMutex = 0;
    afs_uint32 hash;
    cm_cell_rock_t rock;
    size_t len;

    if (namep == NULL || !namep[0] || !strcmp(namep,CM_IOCTL_FILENAME_NOSLASH))
        return NULL;

    /*
     * Strip off any trailing dots at the end of the cell name.
     * Failure to do so results in an undesireable alias as the
     * result of DNS AFSDB record lookups where a trailing dot
     * has special meaning.
     */
    strncpy(name, namep, CELL_MAXNAMELEN);
    for (len = strlen(namep); len > 0 && namep[len-1] == '.'; len--) {
        name[len-1] = '\0';
    }
    if (len == 0)
        return NULL;
    namep = name;

    hash = CM_CELL_NAME_HASH(namep);

    lock_ObtainRead(&cm_cellLock);
    for (cp = cm_data.cellNameHashTablep[hash]; cp; cp=cp->nameNextp) {
        if (cm_stricmp_utf8(namep, cp->name) == 0) {
            strncpy(fullname, cp->name, CELL_MAXNAMELEN);
            fullname[CELL_MAXNAMELEN-1] = '\0';
            break;
        }
    }

    if (!cp) {
        for (cp = cm_data.allCellsp; cp; cp=cp->allNextp) {
            if (strnicmp(namep, cp->name, strlen(namep)) == 0) {
                strncpy(fullname, cp->name, CELL_MAXNAMELEN);
                fullname[CELL_MAXNAMELEN-1] = '\0';
                break;
            }
        }
    }

    if (cp) {
        lock_ReleaseRead(&cm_cellLock);
        cm_UpdateCell(cp, flags);
    } else if (flags & CM_FLAG_CREATE) {
        lock_ConvertRToW(&cm_cellLock);
        hasWriteLock = 1;

        /* when we dropped the lock the cell could have been added
         * to the list so check again while holding the write lock
         */
        for (cp = cm_data.cellNameHashTablep[hash]; cp; cp=cp->nameNextp) {
            if (cm_stricmp_utf8(namep, cp->name) == 0) {
                strncpy(fullname, cp->name, CELL_MAXNAMELEN);
                fullname[CELL_MAXNAMELEN-1] = '\0';
                break;
            }
        }

        if (cp)
            goto done;

        for (cp = cm_data.allCellsp; cp; cp=cp->allNextp) {
            if (strnicmp(namep, cp->name, strlen(namep)) == 0) {
                strncpy(fullname, cp->name, CELL_MAXNAMELEN);
                fullname[CELL_MAXNAMELEN-1] = '\0';
                break;
            }
        }

        if (cp) {
            lock_ReleaseWrite(&cm_cellLock);
            lock_ObtainMutex(&cp->mx);
            lock_ObtainWrite(&cm_cellLock);
            cm_AddCellToNameHashTable(cp);
            cm_AddCellToIDHashTable(cp);
            lock_ReleaseMutex(&cp->mx);
            goto done;
        }

        if ( cm_data.freeCellsp != NULL ) {
            cp = cm_data.freeCellsp;
            cm_data.freeCellsp = cp->freeNextp;

            /*
             * The magic, cellID, and mx fields are already set.
             */
        } else {
            if ( cm_data.currentCells >= cm_data.maxCells )
                osi_panic("Exceeded Max Cells", __FILE__, __LINE__);

            /* don't increment currentCells until we know that we
             * are going to keep this entry
             */
            cp = &cm_data.cellBaseAddress[cm_data.currentCells];
            memset(cp, 0, sizeof(cm_cell_t));
            cp->magic = CM_CELL_MAGIC;

            /* the cellID cannot be 0 */
            cp->cellID = ++cm_data.currentCells;

            /* otherwise we found the cell, and so we're nearly done */
            lock_InitializeMutex(&cp->mx, "cm_cell_t mutex", LOCK_HIERARCHY_CELL);
        }

        lock_ReleaseWrite(&cm_cellLock);
        hasWriteLock = 0;

        rock.cellp = cp;
        rock.flags = flags;
        code = cm_SearchCellRegistry(1, namep, fullname, linkedName, cm_AddCellProc, &rock);
        if (code && code != CM_ERROR_FORCE_DNS_LOOKUP)
            code = cm_SearchCellFileEx(namep, fullname, linkedName, cm_AddCellProc, &rock);
        if (code) {
            osi_Log4(afsd_logp,"in cm_GetCell_gen cm_SearchCellFileEx(%s) returns code= %d fullname= %s linkedName= %s",
                      osi_LogSaveString(afsd_logp,namep), code, osi_LogSaveString(afsd_logp,fullname),
                      osi_LogSaveString(afsd_logp,linkedName));

            if (cm_dnsEnabled) {
                int ttl;

                code = cm_SearchCellByDNS(namep, fullname, &ttl, cm_AddCellProc, &rock);
                if ( code ) {
                    osi_Log3(afsd_logp,"in cm_GetCell_gen cm_SearchCellByDNS(%s) returns code= %d fullname= %s",
                             osi_LogSaveString(afsd_logp,namep), code, osi_LogSaveString(afsd_logp,fullname));
                    lock_ObtainMutex(&cp->mx);
                    lock_ObtainWrite(&cm_cellLock);
                    hasWriteLock = 1;
                    cm_RemoveCellFromIDHashTable(cp);
                    cm_RemoveCellFromNameHashTable(cp);
                    lock_ReleaseMutex(&cp->mx);
                    cm_FreeCell(cp);
                    cp = NULL;
                    goto done;
                } else {   /* got cell from DNS */
                    lock_ObtainMutex(&cp->mx);
                    hasMutex = 1;
                    _InterlockedOr(&cp->flags, CM_CELLFLAG_DNS);
                    _InterlockedAnd(&cp->flags, ~CM_CELLFLAG_VLSERVER_INVALID);
                    cp->timeout = time(0) + ttl;
                }
            }
            else
            {
                lock_ObtainMutex(&cp->mx);
                lock_ObtainWrite(&cm_cellLock);
                hasWriteLock = 1;
                cm_RemoveCellFromIDHashTable(cp);
                cm_RemoveCellFromNameHashTable(cp);
                lock_ReleaseMutex(&cp->mx);
                cm_FreeCell(cp);
                cp = NULL;
                goto done;
	    }
        } else {
            lock_ObtainMutex(&cp->mx);
            hasMutex = 1;
	    cp->timeout = time(0) + 7200;	/* two hour timeout */
	}

        /* we have now been given the fullname of the cell.  It may
         * be that we already have a cell with that name.  If so,
         * we should use it instead of completing the allocation
         * of a new cm_cell_t
         */
        lock_ObtainRead(&cm_cellLock);
        hash = CM_CELL_NAME_HASH(fullname);
        for (cp2 = cm_data.cellNameHashTablep[hash]; cp2; cp2=cp2->nameNextp) {
            if (cm_stricmp_utf8(fullname, cp2->name) == 0) {
                break;
            }
        }

        if (cp2) {
            if (!hasMutex) {
                lock_ObtainMutex(&cp->mx);
                hasMutex = 1;
            }
            lock_ConvertRToW(&cm_cellLock);
            hasWriteLock = 1;
            cm_RemoveCellFromIDHashTable(cp);
            cm_RemoveCellFromNameHashTable(cp);
            lock_ReleaseMutex(&cp->mx);
            hasMutex = 0;
            cm_FreeCell(cp);
            cp = cp2;
            goto done;
        }
        lock_ReleaseRead(&cm_cellLock);

        /* randomise among those vlservers having the same rank*/
        cm_RandomizeServer(&cp->vlServersp);

        if (!hasMutex)
            lock_ObtainMutex(&cp->mx);

        /* copy in name */
        strncpy(cp->name, fullname, CELL_MAXNAMELEN);
        cp->name[CELL_MAXNAMELEN-1] = '\0';

        strncpy(cp->linkedName, linkedName, CELL_MAXNAMELEN);
        cp->linkedName[CELL_MAXNAMELEN-1] = '\0';

        lock_ObtainWrite(&cm_cellLock);
        hasWriteLock = 1;
        cm_AddCellToNameHashTable(cp);
        cm_AddCellToIDHashTable(cp);
        lock_ReleaseMutex(&cp->mx);
        hasMutex = 0;

        /* append cell to global list */
        if (cm_data.allCellsp == NULL) {
            cm_data.allCellsp = cp;
        } else {
            for (cp2 = cm_data.allCellsp; cp2->allNextp; cp2=cp2->allNextp)
                ;
            cp2->allNextp = cp;
        }
        cp->allNextp = NULL;

    } else {
        lock_ReleaseRead(&cm_cellLock);
    }
  done:
    if (hasMutex && cp)
        lock_ReleaseMutex(&cp->mx);
    if (hasWriteLock)
        lock_ReleaseWrite(&cm_cellLock);

    /* fullname is not valid if cp == NULL */
    if (newnamep) {
        if (cp) {
            strncpy(newnamep, fullname, CELL_MAXNAMELEN);
            newnamep[CELL_MAXNAMELEN-1]='\0';
        } else {
            newnamep[0] = '\0';
        }
    }

    if (cp && cp->linkedName[0]) {
        cm_cell_t * linkedCellp = NULL;

        if (!strcmp(cp->name, cp->linkedName)) {
            cp->linkedName[0] = '\0';
        } else if (!(flags & CM_FLAG_NOMOUNTCHASE)) {
            linkedCellp = cm_GetCell(cp->linkedName, CM_FLAG_CREATE|CM_FLAG_NOPROBE|CM_FLAG_NOMOUNTCHASE);

            lock_ObtainWrite(&cm_cellLock);
            if (!linkedCellp ||
                (linkedCellp->linkedName[0] && strcmp(cp->name, linkedCellp->linkedName))) {
                cp->linkedName[0] = '\0';
            } else {
                strncpy(linkedCellp->linkedName, cp->name, CELL_MAXNAMELEN);
                linkedCellp->linkedName[CELL_MAXNAMELEN-1]='\0';
            }
            lock_ReleaseWrite(&cm_cellLock);
        }
    }
    return cp;
}
Exemple #5
0
main_BasicTest(HANDLE hWnd)
{
	long mod1ID;
	long mod2ID;
	long scan1ID;
	long scan2ID;
	HANDLE mod1Handle;
	HANDLE mod2Handle;
	HANDLE scan1Handle;
	HANDLE scan2Handle;
	long localDone;

	osi_Init();

        if (main_logp == NULL) {
        	main_logp = osi_LogCreate("basic", 0);
                osi_LogEnable(main_logp);
                osi_SetStatLog(main_logp);
        }

	/* create three processes, two modifiers and one scanner.  The scanner
	 * checks that the basic invariants are being maintained, while the
	 * modifiers modify the global variables, maintaining certain invariants
	 * by using locks.
	 *
	 * The invariant is that global variables a and b total 100.
	 */
	a = 100;
	b = 0;
	done = 0;

	lock_InitializeRWLock(&main_doneRWLock, "done lock");
	lock_InitializeRWLock(&main_bRWLock, "b lock");
	lock_InitializeMutex(&main_aMutex, "a mutex");

	mod1Handle = CreateThread((SECURITY_ATTRIBUTES *) 0, 0,
		(LPTHREAD_START_ROUTINE) main_Mod1, 0, 0, &mod1ID);
	if (mod1Handle == NULL) return -1;

	mod2Handle = CreateThread((SECURITY_ATTRIBUTES *) 0, 0,
		(LPTHREAD_START_ROUTINE) main_Mod2, 0, 0, &mod2ID);
	if (mod2Handle == NULL) return -2;

	scan1Handle = CreateThread((SECURITY_ATTRIBUTES *) 0, 0,
		(LPTHREAD_START_ROUTINE) main_Scan1, 0, 0, &scan1ID);
	if (scan1Handle== NULL) return -2;

	scan2Handle = CreateThread((SECURITY_ATTRIBUTES *) 0, 0,
		(LPTHREAD_START_ROUTINE) main_Scan2, 0, 0, &scan2ID);
	if (scan2Handle== NULL) return -2;

	/* start running check daemon */
	while (1) {
		Sleep(1000);
		wsprintf(main_screenText[1], "Mod1 iteration %d", m1Loops);
		wsprintf(main_screenText[2], "Mod2 iteration %d", m2Loops);
		wsprintf(main_screenText[3], "Scan1 iteration %d", s1Loops);
		wsprintf(main_screenText[4], "Scan2 iteration %d, %d opportunites seen",
			s2Loops, s2Events);
		main_ForceDisplay(hWnd);

		/* copy out count of # of dudes finished */
		lock_ObtainRead(&main_doneRWLock);
		localDone = done;
		lock_ReleaseRead(&main_doneRWLock);

		/* right now, we're waiting for 4 threads */
		if (localDone == 4) break;
	}

	wsprintf(main_screenText[0], "Test done.");
	main_ForceDisplay(hWnd);

	/* done, release and finalize all locks */
	lock_FinalizeRWLock(&main_doneRWLock);
	lock_FinalizeRWLock(&main_bRWLock);
	lock_FinalizeMutex(&main_aMutex);

	/* finally clean up thread handles */
	CloseHandle(mod1Handle);
	CloseHandle(mod2Handle);
	CloseHandle(scan1Handle);
	CloseHandle(scan2Handle);

	return 0;
}