int NonBlockingWait(double waitint, double timeout, int socket)
  {
    double start = GetTimeInSeconds();
    while(1){
      if(timeout > 0 && GetTimeInSeconds() - start > timeout)
        return 2; // timeout
      if(_client->getPid() < 0 || (_client->getExecutable().empty() &&
                                   !CTX::instance()->solver.listen))
        return 1; // process has been killed or we stopped listening
      // check if there is data (call select with a zero timeout to
      // return immediately, i.e., do polling)
      int ret = Select(0, 0, socket);
      if(ret == 0){ // nothing available
        if(timeout < 0){
          // if asked, refresh the onelab GUI, but no more than every 1/4th of
          // a second
          static double lastRefresh = 0.;
          if(start - lastRefresh > 0.25){
            std::vector<onelab::string> ps;
            onelab::server::instance()->get(ps, "Gmsh/Action");
            if(ps.size() && ps[0].getValue() == "refresh"){
              ps[0].setVisible(false);
              ps[0].setValue("");
              onelab::server::instance()->set(ps[0]);
#if defined(HAVE_FLTK)
              if(FlGui::available()) onelab_cb(0, (void*)"refresh");
#endif
            }
            lastRefresh = start;
          }
        }
        // wait at most waitint seconds and respond to FLTK events
#if defined(HAVE_FLTK)
        if(FlGui::available()) FlGui::instance()->wait(waitint);
#endif
        // return to caller (we will be back here soon again)
	if(timeout < 0) return 3;
      }
      else if(ret > 0){
        return 0; // data is there!
      }
      else{
        // an error happened
        _client->setPid(-1);
        return 1;
      }
    }
  }
Beispiel #2
0
void Scanner::logTimingStats(const Scanner::TimingStats& stats)
{
	// Prevent divide by zero
	if (stats.numFrames == 0)
	{
		return;
	}

	double now = GetTimeInSeconds();
	double totalTime = now - stats.startTime;

	double accountedTime = stats.meshWritingTime + stats.imageAcquisitionTime + stats.imageProcessingTime + stats.pointMappingTime
			+ stats.pointProcessingTime + stats.rotationTime + stats.pointCloudWritingTime + stats.laserTime + stats.laserMergeTime;

	double unaccountedTime = totalTime - accountedTime;
	double rate = totalTime / stats.numFrames;

	std::cout << "Total Seconds per frame:\t" << rate << std::endl;
	std::cout << "Unaccounted time:\t" << (100.0 * unaccountedTime / totalTime) << "%" << std::endl;
	std::cout << "Image Acquisition:\t" << (100.0 * stats.imageAcquisitionTime / totalTime) << "%, " << (stats.imageAcquisitionTime / stats.numFrames) << " seconds per frame." << std::endl;
	std::cout << "Image Processing:\t" << (100.0 * stats.imageProcessingTime / totalTime) << "%, " << (stats.imageProcessingTime / stats.numFrames) << " seconds per frame." << std::endl;
	std::cout << "Laser Time:\t" << (100.0 * stats.laserTime / totalTime) << "%, " << (stats.laserTime / stats.numFrames) << " seconds per frame." << std::endl;
	std::cout << "Point Mapping:\t" << (100.0 * stats.pointMappingTime / totalTime) << "%" << std::endl;
	std::cout << "Point Rotating:\t" << (100.0 * stats.pointProcessingTime / totalTime) << "%" << std::endl;
	std::cout << "Table Rotation:\t" << (100.0 * stats.rotationTime / totalTime) << "%" << std::endl;
	std::cout << "Laser Merging:\t" << (100.0 * stats.laserMergeTime / totalTime) << "%" << std::endl;
	std::cout << "Point Cloud Writing:\t" << (100.0 * stats.pointCloudWritingTime / totalTime) << "%" << std::endl;
	std::cout << "Mesh Writing:\t" << (100.0 * stats.meshWritingTime / totalTime) << "%" << std::endl;
	std::cout << "Num Frame Retries:\t" << stats.numFrameRetries << std::endl;
	std::cout << "Num Frames:\t" << stats.numFrames << std::endl;
	std::cout << "Total Time (min):\t" << (totalTime / 60.0) << std::endl << std::endl;
}
//----------------------------------------------------------------------------
void GelatinCube::PhysicsTick ()
{
    mModule->Update((float)GetTimeInSeconds());

    // Update spline surface.  Remember that the spline maintains its own
    // copy of the control points, so this update is necessary.
    int numSlices = mModule->GetNumSlices() - 2;
    int numRows = mModule->GetNumRows() - 2;
    int numCols = mModule->GetNumCols() - 2;

    for (int s = 0; s < numSlices; ++s)
    {
        for (int r = 0; r < numRows; ++r)
        {
            for (int c = 0; c < numCols; ++c)
            {
                mSpline->SetControlPoint(c, r, s,
                    mModule->Position(s + 1, r + 1, c + 1));
            }
        }
    }

    mBox->UpdateSurface();

    for (int i = 0; i < mBox->GetNumChildren(); ++i)
    {
        TriMesh* mesh = StaticCast<TriMesh>(mBox->GetChild(i));
        mRenderer->Update(mesh->GetVertexBuffer());
    }
}
Beispiel #4
0
//----------------------------------------------------------------------------
void Rope::OnIdle ()
{
    MeasureTime();
    MoveCamera();
    if ( MoveObject() )
        m_spkScene->UpdateGS(0.0f);

    float fCurrIdle = GetTimeInSeconds();
    float fDiff = fCurrIdle - m_fLastIdle;
    if ( fDiff >= 0.001f )
    {
        m_fLastIdle = fCurrIdle;

        DoPhysical();

        ms_spkRenderer->ClearBuffers();
        if ( ms_spkRenderer->BeginScene() )
        {
            ms_spkRenderer->Draw(m_spkScene);
            ms_spkRenderer->EndScene();
        }
        ms_spkRenderer->DisplayBackBuffer();
    }

    UpdateClicks();
}
//----------------------------------------------------------------------------
bool WaterDropFormation::OnInitialize ()
{
	if (!WindowApplication3::OnInitialize())
	{
		return false;
	}

	CreateScene();

	// Center-and-fit for camera viewing.
	mScene->Update();
	mTrnNode->LocalTransform.SetTranslate(-mScene->WorldBound.GetCenter());
	mCamera->SetFrustum(60.0f, GetAspectRatio(), 0.1f, 1000.0f);
	float angle = 0.01f*Mathf::PI;
	float cs = Mathf::Cos(angle), sn = Mathf::Sin(angle);
	AVector camDVector(-cs, 0.0f, -sn);
	AVector camUVector(sn, 0.0f, -cs);
	AVector camRVector = camDVector.Cross(camUVector);
	APoint camPosition = APoint::ORIGIN -
	                     0.9f*mScene->WorldBound.GetRadius()*camDVector;
	mCamera->SetFrame(camPosition, camDVector, camUVector, camRVector);

	// Initial update of objects.
	mScene->Update();

	// Initial culling of scene.
	mCuller.SetCamera(mCamera);
	mCuller.ComputeVisibleSet(mScene);

	InitializeCameraMotion(0.01f, 0.001f);
	InitializeObjectMotion(mScene);

	mLastSeconds = (float)GetTimeInSeconds();
	return true;
}
Beispiel #6
0
//----------------------------------------------------------------------------
void Skinning::OnIdle ()
{
    MeasureTime();

    UpdateConstants((float)GetTimeInSeconds());

    if (MoveCamera())
    {
        mCuller.ComputeVisibleSet(mScene);
    }

    if (MoveObject())
    {
        mScene->Update();
        mCuller.ComputeVisibleSet(mScene);
    }

    if (mRenderer->PreDraw())
    {
        mRenderer->ClearBuffers();
        mRenderer->Draw(mCuller.GetVisibleSet());
        DrawFrameRate(8, GetHeight()-8, mTextColor);
        mRenderer->PostDraw();
        mRenderer->DisplayColorBuffer();
    }

    UpdateFrameCount();
}
//----------------------------------------------------------------------------
bool WaterDropFormation::OnInitialize ()
{
    if ( !Application::OnInitialize() )
        return false;

    // create scene
    m_spkScene = new Node;
    m_spkTrnNode = new Node(3);
    m_spkScene->AttachChild(m_spkTrnNode);
    CreatePlane();
    CreateWall();
    CreateWaterRoot();

    // wireframe
    m_spkWireframe = new WireframeState;
    m_spkScene->SetRenderState(m_spkWireframe);

    // depth buffer
    ZBufferState* pkZBuffer = new ZBufferState;
    pkZBuffer->Enabled() = true;
    pkZBuffer->Writeable() = true;
    pkZBuffer->Compare() = ZBufferState::CF_LEQUAL;
    m_spkScene->SetRenderState(pkZBuffer);

    Configuration0();

    // center-and-fit for camera viewing
    m_spkScene->UpdateGS(0.0f);
    Bound kWBound = m_spkScene->WorldBound();
    m_spkTrnNode->Translate() = -kWBound.Center();
    ms_spkCamera->SetFrustum(0.1f,1000.0f,-0.055f,0.055f,0.04125f,-0.04125f);
    float fAngle = 0.01f*Mathf::PI;
    float fCos = Mathf::Cos(fAngle), fSin = Mathf::Sin(fAngle);
    Vector3f kCUp(fSin,0.0f,-fCos);
    Vector3f kCDir(-fCos,0.0f,-fSin);
    Vector3f kCLeft(0.0f,1.0f,0.0f);
    Vector3f kCLoc = -0.9f*kWBound.Radius()*kCDir;
    ms_spkCamera->SetFrame(kCLoc,kCLeft,kCUp,kCDir);

    // initial update of objects
    ms_spkCamera->Update();
    m_spkScene->UpdateGS(0.0f);
    m_spkScene->UpdateRS();

    m_spkMotionObject = m_spkScene;
    m_bTurretActive = true;
    SetTurretAxes();
    m_fTrnSpeed = 0.01f;
    m_fRotSpeed = 0.001f;

    m_fLastSeconds = GetTimeInSeconds();

    return true;
}
Beispiel #8
0
//----------------------------------------------------------------------------
void IntersectingRectangles::OnIdle ()
{
#ifndef SINGLE_STEP
    float currIdle = (float)GetTimeInSeconds();
    float diff = currIdle - mLastIdle;
    if (diff >= 1.0f/30.0f)
    {
        ModifyRectangles();
        OnDisplay();
        mLastIdle = currIdle;
    }
#endif
}
//----------------------------------------------------------------------------
void WrigglingSnake::ModifyCurve ()
{
    // perturb the snake medial curve
    float fTime = GetTimeInSeconds();
    for (int i = 0; i < m_iNumCtrl; i++)
    {
        Vector3f kCtrl = m_pkCenter->GetControlPoint(i);
        kCtrl.Z() = m_afAmplitude[i]*Mathf::Sin(3.0f*fTime+m_afPhase[i]);
        m_pkCenter->SetControlPoint(i,kCtrl);
    }

    UpdateSnake();
}
Beispiel #10
0
		void AddTimer (int timerID, double interval, double delaySeconds=0, 
			void *act=0, void *userData=0)
		{
			TIMER *timer = new0 TIMER;
			timer->mTimerID = timerID;
			timer->mInterval = interval;
			timer->Action = act;
			timer->UserData = userData;
			double startTime = GetTimeInSeconds();
			timer->StartTime = (float)startTime;
			startTime += delaySeconds;
			mMapTimers.insert(std::make_pair(startTime, timer));
		}
//----------------------------------------------------------------------------
void WrigglingSnake::ModifyCurve ()
{
    // Perturb the snake medial curve.
    float time = (float)GetTimeInSeconds();
    for (int i = 0; i < mNumCtrlPoints; ++i)
    {
        Vector3f ctrl = mCenter->GetControlPoint(i);
        ctrl.Z() = mAmplitudes[i]*Mathf::Sin(3.0f*time + mPhases[i]);
        mCenter->SetControlPoint(i, ctrl);
    }

    UpdateSnake();
}
//----------------------------------------------------------------------------
void IntersectingBoxes::PhysicsTick ()
{
    if (mDoSimulation)
    {
        float currIdle = (float)GetTimeInSeconds();
        float diff = currIdle - mLastIdle;
        if (diff >= 1.0f/30.0f)
        {
            ModifyBoxes();
            mLastIdle = currIdle;
        }
    }
}
//----------------------------------------------------------------------------
FreeFormDeformation::FreeFormDeformation ()
    :
    WindowApplication3("SamplePhysics/FreeFormDeformation", 0, 0, 640, 480,
        Float4(0.5f, 0.0f, 1.0f, 1.0f)),
        mTextColor(1.0f, 1.0f, 1.0f, 1.0f)
{
    mQuantity = 4;
    mDegree = 3;
    mVolume = 0;
    mParameters = 0;
    mDoRandom = false;
    mAmplitude = 0.01f;
    mRadius = 0.25f;
    mLastUpdateTime = (float)GetTimeInSeconds();
    mMouseDown = false;
}
//----------------------------------------------------------------------------
void FreeFormDeformation::OnIdle ()
{
    MeasureTime();

    bool needsCulling = false;
    if (MoveCamera())
    {
        needsCulling = true;
    }

    if (MoveObject())
    {
        mScene->Update();
        needsCulling = true;
        mCuller.ComputeVisibleSet(mScene);
    }

    if (mDoRandom)
    {
        // Deform the mesh no faster than 30 frames per second.
        float time = (float)GetTimeInSeconds();
        if (time - mLastUpdateTime >= 0.0333333f)
        {
            mLastUpdateTime = time;
            DoRandomControlPoints();
            mScene->Update();
            needsCulling = true;
        }
    }

    if (needsCulling)
    {
        mCuller.ComputeVisibleSet(mScene);
    }

    // Draw the scene as fast as possible (not limited to 30 fps).
    if (mRenderer->PreDraw())
    {
        mRenderer->ClearBuffers();
        mRenderer->Draw(mCuller.GetVisibleSet());
        DrawFrameRate(8, GetHeight()-8, mTextColor);
        mRenderer->PostDraw();
        mRenderer->DisplayColorBuffer();
    }

    UpdateFrameCount();
}
//----------------------------------------------------------------------------
void WaterDropFormation::OnIdle ()
{
    MeasureTime();

#ifndef SINGLE_STEP
    float fCurrSeconds = GetTimeInSeconds();
    float fDiff = fCurrSeconds - m_fLastSeconds;
    if ( fDiff >= 0.033333f )
    {
        DoPhysical();
        m_fLastSeconds = fCurrSeconds;
    }
#endif

    DoVisual();
    UpdateClicks();
}
Beispiel #16
0
//----------------------------------------------------------------------------
void Cloth::DoPhysical ()
{
    m_pkModule->Update(GetTimeInSeconds());

    // Update spline surface.  Remember that the spline maintains its own
    // copy of the control points, so this update is necessary.
    int iRows = m_pkModule->GetRows();
    int iCols = m_pkModule->GetCols();
    Vector3f** aakCtrlPoint = m_pkModule->Positions2D();
    for (int iRow = 0; iRow < iRows; iRow++)
    {
        for (int iCol = 0; iCol < iCols; iCol++)
            m_pkSpline->SetControlPoint(iRow,iCol,aakCtrlPoint[iRow][iCol]);
    }

    m_spkCloth->UpdateSurface();
}
//----------------------------------------------------------------------------
void WaterDropFormation::OnIdle ()
{
	MeasureTime();

#ifndef SINGLE_STEP
	float currSeconds = (float)GetTimeInSeconds();
	float diff = currSeconds - mLastSeconds;
	if (diff >= 0.033333f)
	{
		PhysicsTick();
		mCuller.ComputeVisibleSet(mScene);
		mLastSeconds = currSeconds;
	}
#endif

	GraphicsTick();

	UpdateFrameCount();
}
//----------------------------------------------------------------------------
void PointInPolyhedron::OnIdle ()
{
    MeasureTime();

    MoveCamera();
    MoveObject();
    mScene->Update(GetTimeInSeconds());
    mCuller.ComputeVisibleSet(mScene);

    if (mRenderer->PreDraw())
    {
        mRenderer->ClearBuffers();
        mRenderer->Draw(mCuller.GetVisibleSet());
        DrawFrameRate(8, GetHeight()-8, mTextColor);
        mRenderer->PostDraw();
        mRenderer->DisplayColorBuffer();
    }

    UpdateFrameCount();
}
Beispiel #19
0
//----------------------------------------------------------------------------
void Rope::OnIdle ()
{
    MeasureTime();

    MoveCamera();
    if (MoveObject())
    {
        mScene->Update();
    }

    float currIdle = (float)GetTimeInSeconds();
    float diff = currIdle - mLastIdle;
    if (diff >= 0.001f)
    {
        mLastIdle = currIdle;
        PhysicsTick();
        GraphicsTick();
    }

    UpdateFrameCount();
}
Beispiel #20
0
void Scanner::prepareScan()
{
	m_status.enter();
	m_running = true;
	m_progress.setPercent(0);

	m_startTimeSec = GetTimeInSeconds();
	m_remainingTime = 0;

	if (m_task == Scanner::GENERATE_SCAN)
	{
		m_progress.setLabel("Scanning");
	}
	else if (m_task == Scanner::GENERATE_DEBUG)
	{
		m_progress.setLabel("Generating debug info");
	}
	else
	{
		m_progress.setLabel("Unknown");
	}

	// Get handles to our hardware devices
	m_camera = Camera::getInstance();
	m_laser = Laser::getInstance();
	m_turnTable = TurnTable::getInstance();

	// Initialize data structures
	m_maxNumLocations = m_camera->getImageHeight();

	delete [] m_laserLocations;
	m_laserLocations = new PixelLocation[m_maxNumLocations];

	delete [] m_columnPoints;
	m_columnPoints = new ColoredPoint[m_camera->getImageWidth()];

	m_status.leave();
}
Beispiel #21
0
//----------------------------------------------------------------------------
void RipplingOcean::SetupShaders ()
{
    // Re-set all the constants

    // AvgDuDxDvDy, Ambient, TexRepeat, fTime
    float fTime;

    if ( m_bStopped )
    {
        fTime = m_fStopTime;
    }
    else
    {
        fTime = GetTimeInSeconds();
    }
    m_spkTriMesh->GetVertexConst("u_f4Constants")->SetData(
        1/24.0f, m_fAmbient, m_fTexRepeat, fTime );

    Vector3f kLightDir(0.0f,1.0f,1.0f);
    kLightDir.Normalize();
    m_spkTriMesh->GetVertexConst("u_f3LightDir")->SetData( kLightDir );
    m_spkTriMesh->GetVertexConst("u_f4WaveDirX")->SetData(0.25f, 0.0f, -0.7f,
        -0.8f);
    m_spkTriMesh->GetVertexConst("u_f4WaveDirY")->SetData(0, 0.15f, -0.7f, 
        0.1f);
    m_spkTriMesh->GetVertexConst("u_f4WaveSpeed")->SetData(
        0.2f*m_fWaveSpeedFactor, 0.15f*m_fWaveSpeedFactor,
        0.4f*m_fWaveSpeedFactor, 0.4f*m_fWaveSpeedFactor);
    m_spkTriMesh->GetVertexConst("u_f4WaveOffset")->SetData(0, 0.2f, 0.3f,
        -0.2f);
    m_spkTriMesh->GetVertexConst("u_f4WaveHeight")->SetData(
        16.0f*m_fWaveHeightFactor, 10.0f*m_fWaveHeightFactor,
        5.8f*m_fWaveHeightFactor, 8.5f*m_fWaveHeightFactor);
    m_spkTriMesh->GetVertexConst("u_f4BumpSpeed")->SetData(
        0.031f*m_fRippleSpeedFactor, 0.04f*m_fRippleSpeedFactor,
        -0.03f*m_fRippleSpeedFactor, 0.02f*m_fRippleSpeedFactor );
}
Beispiel #22
0
//----------------------------------------------------------------------------
void GelatinCube::DoPhysical ()
{
    m_pkModule->Update(GetTimeInSeconds());

    // Update spline surface.  Remember that the spline maintains its own
    // copy of the control points, so this update is necessary.
    int iSlices = m_pkModule->GetSlices()-2;
    int iRows = m_pkModule->GetRows()-2;
    int iCols = m_pkModule->GetCols()-2;

    for (int iSlice = 0; iSlice < iSlices; iSlice++)
    {
        for (int iRow = 0; iRow < iRows; iRow++)
        {
            for (int iCol = 0; iCol < iCols; iCol++)
            {
                m_pkSpline->ControlPoint(iCol,iRow,iSlice) =
                    m_pkModule->Position(iSlice+1,iRow+1,iCol+1);
            }
        }
    }

    m_spkBox->UpdateSurface();
}
Beispiel #23
0
//----------------------------------------------------------------------------
bool Skinning::OnInitialize ()
{
    if ( !Application::OnInitialize() )
        return false;

    m_spkVertShader = VertexShader::Load("Skinning.wvs");

    if ( !m_spkVertShader || !Setup() )
        return true;

    m_spkScene->UpdateGS(0.0f);

    ms_spkCamera->SetFrustum(1.0f,10000.0f,-0.55f,0.55f,0.4125f,-0.4125f);
    Vector3f kCLeft(1.0f,0.0f,0.0f);
    Vector3f kCUp(0.0f,1.0f,0.0f);
    Vector3f kCDir(0.0f,0.0f,1.0f);
    Vector3f kCLoc(0.0f, 0.0f, 0.0f);
    ms_spkCamera->SetFrame(kCLoc,kCLeft,kCUp,kCDir);

    // initial update of objects
    ms_spkCamera->Update();
    m_spkScene->UpdateGS(0.0f);
    m_spkScene->UpdateRS();

    m_spkMotionObject = m_spkTriMesh;
    m_fTrnSpeed = 0.01f;
    m_fRotSpeed = 0.001f;
    m_bTurretActive = true;
    SetTurretAxes();

    m_fTime = GetTimeInSeconds();

    m_bShaderEnabled = true;
    m_bInitialized = true;
    return true;
}
Beispiel #24
0
//----------------------------------------------------------------------------
bool RipplingOcean::Setup ()
{
    m_bStopped = false;
    m_fStopTime = GetTimeInSeconds();

    m_spkScene = new Node(1);
    m_spkTrnNode = new Node(1);
    m_spkScene->AttachChild(m_spkTrnNode);

    // Root node for a scene graph that contains a bump-mapped triangle mesh
    // square.
    m_spkModel = new Node(1);

    // create the triangle mesh surface
    TriMesh* pkMesh = NULL;
    CreateRectangleMesh(pkMesh, Vector3f::ZERO,
        Vector3f::UNIT_X, Vector3f::UNIT_Y, -Vector3f::UNIT_Z,
        1400.0f, 1200.0f, 50, 50, true, true, true);

    m_spkTriMesh = pkMesh;

    m_spkTriMesh->SetVertexShader(m_spkVertShader);
    m_spkTriMesh->SetPixelShader(m_spkPixShader);
    SetupShaders();

    Image* pkNormal = Image::Load("plasma.mif");
    if ( !pkNormal )
        return false;

    HeightToNormalMap( pkNormal );

    Texture* pkNormalTex = new Texture;
    pkNormalTex->SetImage(pkNormal);
    pkNormalTex->Mipmap() = Texture::MM_LINEAR_LINEAR;
    pkNormalTex->Filter() = Texture::FM_LINEAR;
    pkNormalTex->Apply() = Texture::AM_DECAL;
    pkNormalTex->Wrap() = Texture::WM_WRAP_S_WRAP_T;
    TextureState* pkTS = new TextureState;
    pkTS->Set(0,pkNormalTex);

    Image* pkWater = Image::Load("watergradient.mif");
    if (!pkWater)
        return false;

    Texture* pkWaterTex = new Texture;
    pkWaterTex->SetImage(pkWater);
    pkWaterTex->Apply() = Texture::AM_DECAL;
    pkWaterTex->Wrap() = Texture::WM_CLAMP_S_CLAMP_T;
    pkTS->Set(1,pkWaterTex);

    Image* pkSkySphere = Image::Load("sky.mif");
    if (!pkSkySphere)
        return false;

    Texture* pkSkySphereTex = new Texture;
    pkSkySphereTex->SetImage(pkSkySphere);
    pkTS->Set(2,pkSkySphereTex);

    m_spkTriMesh->SetRenderState(pkTS);

    m_spkModel->AttachChild(m_spkTriMesh);
    m_spkTrnNode->AttachChild(m_spkModel);

    // I'll admit that this is kind of a hack, but it puts the sun
    // a smidge higher in the sky.  It makes it look nicest to start.  =)
    Matrix3f kIncr;
    kIncr.FromAxisAngle(Vector3f::UNIT_X, -0.08f);
    m_spkTrnNode->Rotate() = kIncr; 

    return true;
}
Beispiel #25
0
static
NET_API_STATUS
DisplayUser(LPWSTR lpUserName)
{
    PUSER_MODALS_INFO_0 pUserModals = NULL;
    PUSER_INFO_4 pUserInfo = NULL;
    PLOCALGROUP_USERS_INFO_0 pLocalGroupInfo = NULL;
    PGROUP_USERS_INFO_0 pGroupInfo = NULL;
    DWORD dwLocalGroupRead, dwLocalGroupTotal;
    DWORD dwGroupRead, dwGroupTotal;
    DWORD dwLastSet;
    DWORD i;
    WCHAR szCountry[40];
    INT nPaddedLength = 36;
    NET_API_STATUS Status;

    /* Modify the user */
    Status = NetUserGetInfo(NULL,
                            lpUserName,
                            4,
                            (LPBYTE*)&pUserInfo);
    if (Status != NERR_Success)
        return Status;

    Status = NetUserModalsGet(NULL,
                              0,
                              (LPBYTE*)&pUserModals);
    if (Status != NERR_Success)
        goto done;

    Status = NetUserGetLocalGroups(NULL,
                                   lpUserName,
                                   0,
                                   0,
                                   (LPBYTE*)&pLocalGroupInfo,
                                   MAX_PREFERRED_LENGTH,
                                   &dwLocalGroupRead,
                                   &dwLocalGroupTotal);
    if (Status != NERR_Success)
        goto done;

    Status = NetUserGetGroups(NULL,
                              lpUserName,
                              0,
                              (LPBYTE*)&pGroupInfo,
                              MAX_PREFERRED_LENGTH,
                              &dwGroupRead,
                              &dwGroupTotal);
    if (Status != NERR_Success)
        goto done;

    PrintPaddedMessageString(4411, nPaddedLength);
    ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_name);

    PrintPaddedMessageString(4412, nPaddedLength);
    ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_full_name);

    PrintPaddedMessageString(4413, nPaddedLength);
    ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_comment);

    PrintPaddedMessageString(4414, nPaddedLength);
    ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_usr_comment);

    PrintPaddedMessageString(4416, nPaddedLength);
    GetCountryFromCountryCode(pUserInfo->usri4_country_code,
                              ARRAYSIZE(szCountry), szCountry);
    ConPrintf(StdOut, L"%03ld (%s)\n", pUserInfo->usri4_country_code, szCountry);

    PrintPaddedMessageString(4419, nPaddedLength);
    if (pUserInfo->usri4_flags & UF_ACCOUNTDISABLE)
        PrintMessageString(4301);
    else if (pUserInfo->usri4_flags & UF_LOCKOUT)
        PrintMessageString(4440);
    else
        PrintMessageString(4300);
    ConPuts(StdOut, L"\n");

    PrintPaddedMessageString(4420, nPaddedLength);
    if (pUserInfo->usri4_acct_expires == TIMEQ_FOREVER)
        PrintMessageString(4305);
    else
        PrintDateTime(pUserInfo->usri4_acct_expires);
    ConPuts(StdOut, L"\n\n");

    PrintPaddedMessageString(4421, nPaddedLength);
    dwLastSet = GetTimeInSeconds() - pUserInfo->usri4_password_age;
    PrintDateTime(dwLastSet);
    ConPuts(StdOut, L"\n");

    PrintPaddedMessageString(4422, nPaddedLength);
    if ((pUserInfo->usri4_flags & UF_DONT_EXPIRE_PASSWD) || pUserModals->usrmod0_max_passwd_age == TIMEQ_FOREVER)
        PrintMessageString(4305);
    else
        PrintDateTime(dwLastSet + pUserModals->usrmod0_max_passwd_age);
    ConPuts(StdOut, L"\n");

    PrintPaddedMessageString(4423, nPaddedLength);
    PrintDateTime(dwLastSet + pUserModals->usrmod0_min_passwd_age);
    ConPuts(StdOut, L"\n");

    PrintPaddedMessageString(4437, nPaddedLength);
    PrintMessageString((pUserInfo->usri4_flags & UF_PASSWD_NOTREQD) ? 4301 : 4300);
    ConPuts(StdOut, L"\n");

    PrintPaddedMessageString(4438, nPaddedLength);
    PrintMessageString((pUserInfo->usri4_flags & UF_PASSWD_CANT_CHANGE) ? 4301 : 4300);
    ConPuts(StdOut, L"\n\n");

    PrintPaddedMessageString(4424, nPaddedLength);
    if (pUserInfo->usri4_workstations == NULL || wcslen(pUserInfo->usri4_workstations) == 0)
        PrintMessageString(4302);
    else
        ConPrintf(StdOut, L"%s", pUserInfo->usri4_workstations);
    ConPuts(StdOut, L"\n");

    PrintPaddedMessageString(4429, nPaddedLength);
    ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_script_path);

    PrintPaddedMessageString(4439, nPaddedLength);
    ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_profile);

    PrintPaddedMessageString(4436, nPaddedLength);
    ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_home_dir);

    PrintPaddedMessageString(4430, nPaddedLength);
    if (pUserInfo->usri4_last_logon == 0)
        PrintMessageString(4305);
    else
        PrintDateTime(pUserInfo->usri4_last_logon);
    ConPuts(StdOut, L"\n\n");

    PrintPaddedMessageString(4432, nPaddedLength);
    if (pUserInfo->usri4_logon_hours == NULL)
        PrintMessageString(4302);
    ConPuts(StdOut, L"\n\n");

    ConPuts(StdOut, L"\n");
    PrintPaddedMessageString(4427, nPaddedLength);
    if (dwLocalGroupTotal != 0 && pLocalGroupInfo != NULL)
    {
        for (i = 0; i < dwLocalGroupTotal; i++)
        {
            if (i != 0)
                PrintPadding(L' ', nPaddedLength);
            ConPrintf(StdOut, L"*%s\n", pLocalGroupInfo[i].lgrui0_name);
        }
    }
    else
    {
        ConPuts(StdOut, L"\n");
    }

    PrintPaddedMessageString(4431, nPaddedLength);
    if (dwGroupTotal != 0 && pGroupInfo != NULL)
    {
        for (i = 0; i < dwGroupTotal; i++)
        {
            if (i != 0)
                PrintPadding(L' ', nPaddedLength);
            ConPrintf(StdOut, L"*%s\n", pGroupInfo[i].grui0_name);
        }
    }
    else
    {
        ConPuts(StdOut, L"\n");
    }

done:
    if (pGroupInfo != NULL)
        NetApiBufferFree(pGroupInfo);

    if (pLocalGroupInfo != NULL)
        NetApiBufferFree(pLocalGroupInfo);

    if (pUserModals != NULL)
        NetApiBufferFree(pUserModals);

    if (pUserInfo != NULL)
        NetApiBufferFree(pUserInfo);

    return NERR_Success;
}
Beispiel #26
0
void Scanner::run()
{
	// Prepare to scan
	prepareScan();

	// Set the base output file
	std::stringstream sstr;
	sstr << SCAN_OUTPUT_DIR << std::string("/") << time(NULL);

	m_filename = sstr.str();

	m_firstRowRightLaserCol = m_camera->getImageWidth() * 0.5;
	m_firstRowLeftLaserCol = m_camera->getImageWidth() * 0.5;

	Scanner::TimingStats timingStats;
	memset(&timingStats, 0, sizeof(Scanner::TimingStats));
	timingStats.startTime = GetTimeInSeconds();
	double time1 = 0;

	Setup * setup = Setup::get();
	Preset preset = PresetManager::get()->getActivePreset();

	// Read the laser selection
	m_laserSelection = preset.laserSide;

	// Read the location of the lasers and camera
	m_rightLaserLoc = setup->rightLaserLocation;
	m_leftLaserLoc = setup->leftLaserLocation;
	m_cameraLoc = setup->cameraLocation;

	LocationMapper leftLocMapper(m_leftLaserLoc, m_cameraLoc);
	LocationMapper rightLocMapper(m_rightLaserLoc, m_cameraLoc);

	// Compute the angle between the two laser planes
	real leftLaserX = ABS(m_leftLaserLoc.x);
	real rightLaserX = ABS(m_rightLaserLoc.x);
	real camZ = ABS(m_cameraLoc.z);

	// Sanity check to prevent divide by 0.  In reality the laser should never be this close to the camera
	if (leftLaserX < 0.001)
	{
		leftLaserX = 0.001;
	}

	if (rightLaserX < 0.001)
	{
		rightLaserX = 0.001;
	}

	//
	// tan(theta) = ABS(laserX) / camZ
	// theta = atan(ABS(laserX) / camZ)
	//
	real leftLaserAngle = atan(leftLaserX / camZ);
	real rightLaserAngle = atan(rightLaserX / camZ);

	m_radiansBetweenLaserPlanes = leftLaserAngle + rightLaserAngle;

	// Write the range CSV
	if (m_writeRangeCsvEnabled)
	{
		m_rangeFout.open((m_filename + ".csv").c_str());
		if (!m_rangeFout.is_open())
		{
			throw Exception("Error opening range CSV file");
		}
	}

	// Init the results vectors
	m_results.enter();
	m_leftLaserResults.clear();
	m_rightLaserResults.clear();
	m_results.leave();

	int numFrames = 0;

	int maxFramesPerRevolution = preset.framesPerRevolution;
	if (maxFramesPerRevolution < 1)
	{
		maxFramesPerRevolution = 1;
	}

	int stepsPerRevolution = Setup::get()->stepsPerRevolution;
	if (maxFramesPerRevolution > stepsPerRevolution)
	{
		maxFramesPerRevolution = stepsPerRevolution;
	}

	try
	{
		// Enable the turn table motor
		m_turnTable->setMotorEnabled(true);
		std::cout << "Enabled motor" << std::endl;

		if (m_laser == NULL)
		{
			throw Exception("Laser object is NULL");
		}

		if (m_turnTable == NULL)
		{
			throw Exception("Laser object is NULL");
		}

		float rotation = 0;

		// Read the number of motor steps per revolution
		int stepsPerRevolution = setup->stepsPerRevolution;

		float rangeRadians =  (m_range / 360) * (2 * PI);

		// The number of steps for a single frame
		int stepsPerFrame = ceil(stepsPerRevolution / (float)maxFramesPerRevolution);
		if (stepsPerFrame < 1)
		{
			stepsPerFrame = 1;
		}

		// The number of radians a single step takes you
		m_radiansPerFrame = ((2 * PI) / (float) stepsPerRevolution);

		// The radians to move for a single frame
		float frameRadians = stepsPerFrame * m_radiansPerFrame;

		numFrames = ceil(rangeRadians / frameRadians);

		m_numFramesBetweenLaserPlanes = m_radiansBetweenLaserPlanes / frameRadians;

		std::cout << "Angle between laser planes: " << RADIANS_TO_DEGREES(m_radiansBetweenLaserPlanes)
				  << " degrees, radiansPerFrame=" << m_radiansPerFrame
				  << ", numFramesBetweenLaserPlanes=" << m_numFramesBetweenLaserPlanes
				  << ", numFrames=" << numFrames << std::endl;

		for (int iFrame = 0; iFrame < numFrames; iFrame++)
		{
			timingStats.numFrames++;

			// Stop if the user asked us to
			if (m_stopRequested)
			{
				break;
			}

			singleScan(iFrame, rotation, frameRadians, leftLocMapper, rightLocMapper, &timingStats);

			rotation += frameRadians;

			// Update the progress
			double progress = (iFrame + 1.0) / numFrames;
			double timeElapsed = GetTimeInSeconds() - m_startTimeSec;
			double percentComplete = 100.0 * progress;
			double percentPerSecond = percentComplete / timeElapsed;
			double fullTimeSec = 100.0 / percentPerSecond;
			double remainingSec = fullTimeSec - timeElapsed;

			m_progress.setPercent(progress * 100);

			m_status.enter();
			m_remainingTime = remainingSec;
			m_status.leave();

			logTimingStats(timingStats);
			std::cout << percentComplete << "% Complete, " << (remainingSec / 60) << " minutes remaining." << std::endl;
		}
	}
	catch (...)
	{	
		m_turnTable->setMotorEnabled(false);

		m_status.enter();
		m_running = false;
		m_status.leave();

		if (m_writeRangeCsvEnabled)
		{
			m_rangeFout.close();
		}

		throw;
	}
	
	m_rangeFout.close();

	m_turnTable->setMotorEnabled(false);

	std::cout << "Merging laser results..." << std::endl;

	time1 = GetTimeInSeconds();

	// Merge the left and right lasers and sort the results
	std::vector<NeutralFileRecord> results;
	LaserResultsMerger merger;

	m_results.enter();
	merger.merge(results, m_leftLaserResults, m_rightLaserResults, maxFramesPerRevolution,
			     m_numFramesBetweenLaserPlanes, Camera::getInstance()->getImageHeight(), preset.laserMergeAction, m_progress);
	m_results.leave();

	// Sort by pseudo-step and row
	std::cout << "Sort 2... " << std::endl;
	std::sort(results.begin(), results.end(), ComparePseudoSteps);
	std::cout << "End Sort 2... " << std::endl;

	m_results.enter();

	std::cout << "Merged " << m_leftLaserResults.size() << " left laser and " << m_rightLaserResults.size() << " right laser results into " << results.size() << " results." << std::endl;

	m_leftLaserResults.clear();
	m_rightLaserResults.clear();

	m_results.leave();

	std::cout << "Constructing mesh..." << std::endl;

	timingStats.laserMergeTime += GetTimeInSeconds() - time1;

	// Write the PLY file
	std::cout << "Starting output thread..." << std::endl;
	if (preset.generatePly)
	{
		m_progress.setLabel("Generating PLY file");
		m_progress.setPercent(0);

		std::string plyFilename = m_filename + ".ply";

		std::cout << "Writing PLY file... " << plyFilename <<  std::endl;
		time1 = GetTimeInSeconds();

		FileWriter plyOut(plyFilename.c_str());
		if (!plyOut.is_open())
		{
			throw Exception("Error opening file for writing: " + plyFilename);
		}

		/** Writes the results to a PLY file */
		PlyWriter plyWriter;
		plyWriter.setDataFormat(preset.plyDataFormat);
		plyWriter.setTotalNumPoints((int)results.size());
		plyWriter.begin(&plyOut);

		real percent = 0;
		for (size_t iRec = 0; iRec < results.size(); iRec++)
		{
			real newPct = 100.0f * iRec / results.size();
			if (newPct - percent > 0.1)
			{
				m_progress.setPercent(newPct);
				percent = newPct;
			}

			plyWriter.writePoints(&results[iRec].point, 1);
		}

		plyWriter.end();
		plyOut.close();
		timingStats.pointCloudWritingTime += GetTimeInSeconds() - time1;
	}

	// Generate the XYZ file
	if (preset.generateXyz)
	{
		std::cout << "Generating XYZ file..." << std::endl;
		time1 = GetTimeInSeconds();
		XyzWriter xyzWriter;
		xyzWriter.write(m_filename, results, m_progress);
		timingStats.pointCloudWritingTime += GetTimeInSeconds() - time1;
	}

	// Generate the STL file
	if (preset.generateStl)
	{
		std::cout << "Generating STL mesh..." << std::endl;
		time1 = GetTimeInSeconds();
		StlWriter stlWriter;
		stlWriter.write(m_filename, results, m_range > 359, m_progress);
		timingStats.meshWritingTime = GetTimeInSeconds() - time1;
	}

	logTimingStats(timingStats);

	m_progress.setPercent(100);

	m_status.enter();
	m_running = false;
	m_status.leave();

	std::cout << "Done." << std::endl;
}
Beispiel #27
0
void Scanner::singleScan(int frame, float rotation, float frameRotation,
		                 LocationMapper& leftLocMapper, LocationMapper& rightLocMapper, TimingStats * timingStats)
{
	double time1 = GetTimeInSeconds();
	m_turnTable->rotate(frameRotation);
	timingStats->rotationTime += GetTimeInSeconds() - time1;

	// Make sure the laser is off
	m_laser->turnOff(Laser::ALL_LASERS);

	// Take a picture with the laser off
	time1 = GetTimeInSeconds();
	acquireImage(&m_image1);
	timingStats->imageAcquisitionTime += GetTimeInSeconds() - time1;

	// If this is the first image, save it as a thumbnail
	if (frame == 0)
	{
		std::string thumbnail = m_filename + ".png";

		PixelLocationWriter imageWriter;
		imageWriter.writeImage(m_image1, 128, 96, thumbnail.c_str());
	}

	// Scan with the Right laser
	if (m_laserSelection == Laser::RIGHT_LASER || m_laserSelection == Laser::ALL_LASERS)
	{
		bool goodResult = false;

		for (int iTry = 0; iTry < m_maxNumFrameRetries && ! goodResult; iTry++)
		{
			// Turn on the right laser
			time1 = GetTimeInSeconds();
			m_laser->turnOn(Laser::RIGHT_LASER);
			timingStats->laserTime += GetTimeInSeconds() - time1;

			// Take a picture with the right laser on
			time1 = GetTimeInSeconds();
			acquireImage(&m_image2);
			timingStats->imageAcquisitionTime += GetTimeInSeconds() - time1;

			// Turn off the right laser
			time1 = GetTimeInSeconds();
			m_laser->turnOff(Laser::RIGHT_LASER);
			timingStats->laserTime += GetTimeInSeconds() - time1;

			// Process the right laser results
			goodResult = processScan(m_rightLaserResults, frame, rotation, rightLocMapper, Laser::RIGHT_LASER, m_firstRowRightLaserCol, timingStats);

			// If it didn't succeed, take the first image again
			if (!goodResult)
			{
				// Take a picture with the laser off
				time1 = GetTimeInSeconds();
				acquireImage(&m_image1);
				timingStats->imageAcquisitionTime += GetTimeInSeconds() - time1;
			}
		}
	}

	// Scan with the Left laser
	if (m_laserSelection == Laser::LEFT_LASER || m_laserSelection == Laser::ALL_LASERS)
	{
		bool goodResult = false;

		for (int iTry = 0; iTry < m_maxNumFrameRetries && ! goodResult; iTry++)
		{
			// Turn on the left laser
			time1 = GetTimeInSeconds();
			m_laser->turnOn(Laser::LEFT_LASER);
			timingStats->laserTime += GetTimeInSeconds() - time1;

			// Take a picture with the left laser on
			time1 = GetTimeInSeconds();
			acquireImage(&m_image2);
			timingStats->imageAcquisitionTime += GetTimeInSeconds() - time1;

			// Turn off the left laser
			time1 = GetTimeInSeconds();
			m_laser->turnOff(Laser::LEFT_LASER);
			timingStats->laserTime += GetTimeInSeconds() - time1;

			// Process the left laser results
			goodResult = processScan(m_leftLaserResults, frame, rotation, leftLocMapper, Laser::LEFT_LASER, m_firstRowLeftLaserCol, timingStats);

			// If it didn't succeed, take the first image again
			if (!goodResult)
			{
				// Take a picture with the laser off
				time1 = GetTimeInSeconds();
				acquireImage(&m_image1);
				timingStats->imageAcquisitionTime += GetTimeInSeconds() - time1;
			}
		}
	}
}
Beispiel #28
0
bool Scanner::processScan(std::vector<NeutralFileRecord> & results, int frame, float rotation, LocationMapper& locMapper, Laser::LaserSide laserSide, int & firstRowLaserCol, TimingStats * timingStats)
{
	int numLocationsMapped = 0;
	real percentPixelsOverThreshold = 0;

	// Send the pictures off for processing
	double time1 = GetTimeInSeconds();
	int numLocations = m_imageProcessor.process(m_image1,
												m_image2,
												NULL,
												m_laserLocations,
												m_maxNumLocations,
												firstRowLaserCol,
												percentPixelsOverThreshold,
												NULL);

	timingStats->imageProcessingTime += GetTimeInSeconds() - time1;

	// If we had major problems with this frame, try it again
	std::cout << "percentPixelsOverThreshold: " << percentPixelsOverThreshold << std::endl;
	if (percentPixelsOverThreshold > m_maxPercentPixelsOverThreshold)
	{
		std::cout << "!! Many bad laser locations suspected, pctOverThreshold=" << percentPixelsOverThreshold
				  << ", maxPct=" << m_maxPercentPixelsOverThreshold << ", rescanning..." << std::endl;

		timingStats->numFrameRetries++;

		return false;
	}

	std::cout << "Detected " << numLocations << " laser pixels." << std::endl;

	// Lookup the 3D locations for the laser points
	numLocationsMapped = 0;

	if (numLocations > 0)
	{
		time1 = GetTimeInSeconds();
		locMapper.mapPoints(m_laserLocations, &m_image1, m_columnPoints, numLocations, numLocationsMapped);
		timingStats->pointMappingTime += GetTimeInSeconds() - time1;

		if (numLocations != numLocationsMapped)
		{
			std::cout << "Discarded " << numLocations - numLocationsMapped << " points." << std::endl;
		}
	}
	else
	{
		// Stop here if we didn't detect the laser at all
		std::cerr << "!!! Could not detect laser at all" << std::endl;
	}


	// Map the points if there was something to map
	if (numLocationsMapped > 0)
	{
		time1 = GetTimeInSeconds();

		if (m_writeRangeCsvEnabled)
		{
			writeRangePoints(m_columnPoints, numLocationsMapped, laserSide);
		}

		// Rotate the points
		rotatePoints(m_columnPoints, rotation, numLocationsMapped);

		// Write to the neutral file
		time1 = GetTimeInSeconds();
		m_results.enter();
		for (int iLoc = 0; iLoc < numLocationsMapped; iLoc++)
		{
			NeutralFileRecord record;
			record.pixel = m_laserLocations[iLoc];
			record.point = m_columnPoints[iLoc];
			record.rotation = laserSide == Laser::RIGHT_LASER ? rotation : rotation + m_radiansBetweenLaserPlanes;
			record.frame = frame;
			record.laserSide = (int) laserSide;
			results.push_back(record);
		}
		m_results.leave();
		timingStats->pointProcessingTime += GetTimeInSeconds() - time1;
	}

	return true;
}
Beispiel #29
0
//----------------------------------------------------------------------------
void RipplingOcean::OnKeyDown (unsigned char ucKey, int, int)
{
    if ( ucKey == 'q' || ucKey == 'Q' || ucKey == KEY_ESCAPE )
    {
        RequestTermination();
        return;
    }
    else if ( ucKey == 'w' )
    {
        m_fWaveHeightFactor -= 0.1f;
        if ( m_fWaveHeightFactor < 0 )
            m_fWaveHeightFactor = 0;
    }
    else if ( ucKey == 'W' )
    {
        m_fWaveHeightFactor += 0.1f;
    }
    else if ( ucKey == 's' )
    {
        m_fWaveSpeedFactor -= 0.1f;
        if ( m_fWaveSpeedFactor < 0 )
            m_fWaveSpeedFactor = 0;
    }
    else if ( ucKey == 'S' )
    {
        m_fWaveSpeedFactor += 0.1f;
    }
    else if ( ucKey == 'a' )
    {
        m_fAmbient -= 0.05f;
        if ( m_fAmbient < 0 )
            m_fAmbient = 0;
    }
    else if ( ucKey == 'A' )
    {
        m_fAmbient += 0.05f;
        if ( m_fAmbient > 1 )
            m_fAmbient = 1;
    }
    else if ( ucKey == 'r' )
    {
        m_fRippleSpeedFactor -= 0.1f;
        if ( m_fRippleSpeedFactor < 0 )
            m_fRippleSpeedFactor = 0;
    }
    else if ( ucKey == 'R' )
    {
        m_fRippleSpeedFactor += 0.1f;
    }
    else if ( ucKey == 'T' )
    {
        m_fTexRepeat += 0.1f;
    }
    else if ( ucKey == 't' )
    {
        m_fTexRepeat -= 0.1f;
        if ( m_fTexRepeat < 0 )
            m_fTexRepeat = 0;
    }
    else if ( ucKey == ' ' )
    {
        m_bStopped = !m_bStopped;
        m_fStopTime = GetTimeInSeconds();
    }
}
Beispiel #30
0
static
NET_API_STATUS
DisplayUser(LPWSTR lpUserName)
{
    PUSER_MODALS_INFO_0 pUserModals = NULL;
    PUSER_INFO_4 pUserInfo = NULL;
    PLOCALGROUP_USERS_INFO_0 pLocalGroupInfo = NULL;
    PGROUP_USERS_INFO_0 pGroupInfo = NULL;
    DWORD dwLocalGroupRead, dwLocalGroupTotal;
    DWORD dwGroupRead, dwGroupTotal;
    DWORD dwLastSet;
    DWORD i;
    INT nPaddedLength = 29;
    NET_API_STATUS Status;

    /* Modify the user */
    Status = NetUserGetInfo(NULL,
                            lpUserName,
                            4,
                            (LPBYTE*)&pUserInfo);
    if (Status != NERR_Success)
        return Status;

    Status = NetUserModalsGet(NULL,
                              0,
                              (LPBYTE*)&pUserModals);
    if (Status != NERR_Success)
        goto done;

    Status = NetUserGetLocalGroups(NULL,
                                   lpUserName,
                                   0,
                                   0,
                                   (LPBYTE*)&pLocalGroupInfo,
                                   MAX_PREFERRED_LENGTH,
                                   &dwLocalGroupRead,
                                   &dwLocalGroupTotal);
    if (Status != NERR_Success)
        goto done;

    Status = NetUserGetGroups(NULL,
                              lpUserName,
                              0,
                              (LPBYTE*)&pGroupInfo,
                              MAX_PREFERRED_LENGTH,
                              &dwGroupRead,
                              &dwGroupTotal);
    if (Status != NERR_Success)
        goto done;

    PrintPaddedResourceString(IDS_USER_NAME, nPaddedLength);
    ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_name);

    PrintPaddedResourceString(IDS_USER_FULL_NAME, nPaddedLength);
    ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_full_name);

    PrintPaddedResourceString(IDS_USER_COMMENT, nPaddedLength);
    ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_comment);

    PrintPaddedResourceString(IDS_USER_USER_COMMENT, nPaddedLength);
    ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_usr_comment);

    PrintPaddedResourceString(IDS_USER_COUNTRY_CODE, nPaddedLength);
    ConPrintf(StdOut, L"%03ld ()\n", pUserInfo->usri4_country_code);

    PrintPaddedResourceString(IDS_USER_ACCOUNT_ACTIVE, nPaddedLength);
    if (pUserInfo->usri4_flags & UF_ACCOUNTDISABLE)
        ConResPuts(StdOut, IDS_GENERIC_NO);
    else if (pUserInfo->usri4_flags & UF_LOCKOUT)
        ConResPuts(StdOut, IDS_GENERIC_LOCKED);
    else
        ConResPuts(StdOut, IDS_GENERIC_YES);
    ConPuts(StdOut, L"\n");

    PrintPaddedResourceString(IDS_USER_ACCOUNT_EXPIRES, nPaddedLength);
    if (pUserInfo->usri4_acct_expires == TIMEQ_FOREVER)
        ConResPuts(StdOut, IDS_GENERIC_NEVER);
    else
        PrintDateTime(pUserInfo->usri4_acct_expires);
    ConPuts(StdOut, L"\n\n");

    PrintPaddedResourceString(IDS_USER_PW_LAST_SET, nPaddedLength);
    dwLastSet = GetTimeInSeconds() - pUserInfo->usri4_password_age;
    PrintDateTime(dwLastSet);

    PrintPaddedResourceString(IDS_USER_PW_EXPIRES, nPaddedLength);
    if ((pUserInfo->usri4_flags & UF_DONT_EXPIRE_PASSWD) || pUserModals->usrmod0_max_passwd_age == TIMEQ_FOREVER)
        ConResPuts(StdOut, IDS_GENERIC_NEVER);
    else
        PrintDateTime(dwLastSet + pUserModals->usrmod0_max_passwd_age);
    ConPuts(StdOut, L"\n");

    PrintPaddedResourceString(IDS_USER_PW_CHANGEABLE, nPaddedLength);
    PrintDateTime(dwLastSet + pUserModals->usrmod0_min_passwd_age);

    PrintPaddedResourceString(IDS_USER_PW_REQUIRED, nPaddedLength);
    ConResPuts(StdOut, (pUserInfo->usri4_flags & UF_PASSWD_NOTREQD) ? IDS_GENERIC_NO : IDS_GENERIC_YES);
    ConPuts(StdOut, L"\n");

    PrintPaddedResourceString(IDS_USER_CHANGE_PW, nPaddedLength);
    ConResPuts(StdOut, (pUserInfo->usri4_flags & UF_PASSWD_CANT_CHANGE) ? IDS_GENERIC_NO : IDS_GENERIC_YES);
    ConPuts(StdOut, L"\n\n");

    PrintPaddedResourceString(IDS_USER_WORKSTATIONS, nPaddedLength);
    if (pUserInfo->usri4_workstations == NULL || wcslen(pUserInfo->usri4_workstations) == 0)
        ConResPuts(StdOut, IDS_GENERIC_ALL);
    else
        ConPrintf(StdOut, L"%s", pUserInfo->usri4_workstations);
    ConPuts(StdOut, L"\n");

    PrintPaddedResourceString(IDS_USER_LOGON_SCRIPT, nPaddedLength);
    ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_script_path);

    PrintPaddedResourceString(IDS_USER_PROFILE, nPaddedLength);
    ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_profile);

    PrintPaddedResourceString(IDS_USER_HOME_DIR, nPaddedLength);
    ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_home_dir);

    PrintPaddedResourceString(IDS_USER_LAST_LOGON, nPaddedLength);
    if (pUserInfo->usri4_last_logon == 0)
        ConResPuts(StdOut, IDS_GENERIC_NEVER);
    else
        PrintDateTime(pUserInfo->usri4_last_logon);
    ConPuts(StdOut, L"\n\n");

    PrintPaddedResourceString(IDS_USER_LOGON_HOURS, nPaddedLength);
    if (pUserInfo->usri4_logon_hours == NULL)
        ConResPuts(StdOut, IDS_GENERIC_ALL);
    ConPuts(StdOut, L"\n\n");

    ConPuts(StdOut, L"\n");
    PrintPaddedResourceString(IDS_USER_LOCAL_GROUPS, nPaddedLength);
    if (dwLocalGroupTotal != 0 && pLocalGroupInfo != NULL)
    {
        for (i = 0; i < dwLocalGroupTotal; i++)
        {
            if (i != 0)
                PrintPadding(L' ', nPaddedLength);
            ConPrintf(StdOut, L"*%s\n", pLocalGroupInfo[i].lgrui0_name);
        }
    }
    else
    {
        ConPuts(StdOut, L"\n");
    }

    PrintPaddedResourceString(IDS_USER_GLOBAL_GROUPS, nPaddedLength);
    if (dwGroupTotal != 0 && pGroupInfo != NULL)
    {
        for (i = 0; i < dwGroupTotal; i++)
        {
            if (i != 0)
                PrintPadding(L' ', nPaddedLength);
            ConPrintf(StdOut, L"*%s\n", pGroupInfo[i].grui0_name);
        }
    }
    else
    {
        ConPuts(StdOut, L"\n");
    }

done:
    if (pGroupInfo != NULL)
        NetApiBufferFree(pGroupInfo);

    if (pLocalGroupInfo != NULL)
        NetApiBufferFree(pLocalGroupInfo);

    if (pUserModals != NULL)
        NetApiBufferFree(pUserModals);

    if (pUserInfo != NULL)
        NetApiBufferFree(pUserInfo);

    return NERR_Success;
}