コード例 #1
0
void VProcess::_ReadProductVersion( VString& outVersion) const
{
#if VERSIONWIN
#ifndef XTOOLBOX_AS_STANDALONE
	DWORD size = ::GetFileVersionInfoSizeW( GetExecutableFilePath().GetPath().GetCPointer(), NULL);
	void *buffer = malloc( size);
	if ( (buffer != NULL) && GetFileVersionInfoW( GetExecutableFilePath().GetPath().GetCPointer(), NULL, size, buffer))
	{
		void *valueAdress;
		UINT valueSize;
		if (::VerQueryValueW( buffer, L"\\StringFileInfo\\040904B0\\ProductVersion", &valueAdress, &valueSize))
		{
			outVersion.FromBlock( valueAdress, (valueSize - 1) * sizeof( UniChar), VTC_UTF_16);
		}
	}
	if (buffer != NULL)
		free( buffer);
#endif
#elif VERSIONMAC
	// The constant for the "short version" property does not exist.
	CFStringRef cfProductVersion = (CFStringRef) CFBundleGetValueForInfoDictionaryKey( CFBundleGetMainBundle(), CFSTR ( "CFBundleShortVersionString" ) /*kCFBundleVersionKey*/);
	if (cfProductVersion != NULL)
	{
		outVersion.MAC_FromCFString( cfProductVersion);
	}

#elif VERSION_LINUX
    //jmo - We get the Linux product version with SetProductVersion() on VRIAServerApplication init
#endif
}
コード例 #2
0
// [static]
VError XMacSystem::GetProcessorBrandName( XBOX::VString& outProcessorName)
{
	VError error = VE_OK;
	
	static VString sProcessorName;
	
	if (sProcessorName.IsEmpty())
	{
		// machdep.cpu.brand_string n'est dispo que sur intel
		char buffer[512];
		size_t size = sizeof( buffer);
		int	r = ::sysctlbyname( "machdep.cpu.brand_string", buffer, &size, NULL, 0);
		if (testAssert( r == 0))
		{
			sProcessorName.FromBlock( buffer, size, VTC_UTF_8);
		}
		else
		{
			error = VE_UNKNOWN_ERROR;
		}
	}
	
	outProcessorName = sProcessorName;
	
	return error;
}
コード例 #3
0
void VProcess::_ReadProductName( VString& outName) const
{
#if VERSIONWIN
#ifndef XTOOLBOX_AS_STANDALONE
	DWORD size = ::GetFileVersionInfoSizeW( GetExecutableFilePath().GetPath().GetCPointer(), NULL);
	void *buffer = malloc( size);
	if ( (buffer != NULL) && GetFileVersionInfoW( GetExecutableFilePath().GetPath().GetCPointer(), NULL, size, buffer))
	{
		void *valueAdress;
		UINT valueSize;
		if (::VerQueryValueW( buffer, L"\\StringFileInfo\\040904B0\\ProductName", &valueAdress, &valueSize))
		{
			outName.FromBlock( valueAdress, (valueSize - 1) * sizeof( UniChar), VTC_UTF_16);
		}
	}
	if (buffer != NULL)
		free( buffer);
#endif
#elif VERSIONMAC
	CFStringRef cfProductName = (CFStringRef) CFBundleGetValueForInfoDictionaryKey( CFBundleGetMainBundle(), kCFBundleNameKey);
	if (cfProductName != NULL)
		outName.MAC_FromCFString( cfProductName);

#elif VERSION_LINUX
    outName="Wakanda Server";	//Postponed Linux Implementation
#endif
}
コード例 #4
0
//static
void XLinuxSystem::GetHostName(VString& outName)
{
	char name[HOST_NAME_MAX+1];
	name[0]=0;

	int res=gethostname(name, sizeof(name));
	xbox_assert(res==0);

	outName.FromBlock(name, strlen(name), VTC_UTF_8);
}
コード例 #5
0
//static
void XLinuxSystem::GetLoginUserName(VString& outName)
{
	char name[LOGIN_NAME_MAX+1];
	name[0]=0;

	int res=getlogin_r(name, sizeof(name));
	xbox_assert(res==0);

	outName.FromBlock(name, strlen(name), VTC_UTF_8);
}
コード例 #6
0
VString XPosixEnvironmentVariables::GetVariable(const VString& inVariableName, VError& outError)
{
    outError = VE_OK;
    
	VString variableValue = CVSTR("");

	VStringConvertBuffer inVariableNameBuffer(inVariableName, VTC_UTF_8);

	const char* variableBuffer = getenv(inVariableNameBuffer.GetCPointer());

	if (variableBuffer != NULL)
	{
		variableValue.FromBlock(variableBuffer, ::strlen(variableBuffer), VTC_UTF_8);
	}

	return variableValue;
}
コード例 #7
0
bool JS4D::RegisterConstructor( const char *inClassName, JSObjectCallAsConstructorCallback inConstructorCallBack)
{
	VString name;
	name.FromBlock( inClassName, strlen( inClassName), VTC_UTF_8);

	// already registered ?
	xbox_assert( sMapOfConstructorCallback.find( name) == sMapOfConstructorCallback.end());

	try
	{
		sMapOfConstructorCallback.insert( MapOfConstructorCallback::value_type( name, inConstructorCallBack));
	}
	catch(...)
	{
		return false;
	}
	return true;
}
コード例 #8
0
void CALLBACK XWinFileSystemNotification::CompletionRoutine( DWORD inErrorCode, DWORD inBytesTransferred, LPOVERLAPPED inOverlapped )
{
	// We have a list of folders that we are watching, and we want to test to see if any
	// of them have met their change filter requirements yet.  When we get a new folder to
	// watch, we open up the folder's handle and we map it to the parameters required by
	// the ReadDirectoryChangesW API.  Then we have a list of this information socked away
	// that we can then use in a loop.  The basic idea is to test for changes, and if there
	// are some changes, add the information to a queue of data to return to the user.
	//
	// However, we don't return the data to the user immediately.  The user is able to pick
	// a latency for the queue, so that we can return batches of notifications to the user
	// instead of returning them as they happen.  This is important for some uses, because it
	// may be possible for the user to make a lot of changes very quickly (imaging a Perforce
	// fetch, if you will).  A consumer could become quickly swamped with very expensive notification
	// calls unless we queued them up into a list.
	//
	// Since this is being called from a preemptive thread, and the calls to ReadDirectoryChangesW
	// will block if called synchronously, we need to use overlapped (asynchronous) calls in order
	// to process multiple directory watches via a single thread.  We can basically test each handle
	// with a wait time of "none."
	//
	// Once a handle has a change associated with it, we need to scrape the change information out
	// into its own buffer.  Then we can update the latency value associated with the handle so that
	// we don't fire an event immediately for the change.  After all of the handles are updated, we
	// can loop over them again to see if any are ready to send out some notifications, based on whether
	// they have queued data to report, as well as their latency counter.
	//
	// We've been a bit sneaky with the overlapped structure that we pass in.  It's actually a pointer
	// to more memory than the overlapped structure itself -- it's a pointer to our ChangeData structure,
	// of which the OVERLAPPED part happens to be first.  This gives us access to all of the information
	// we need to care about.

	XWinChangeData *data = (XWinChangeData *) ( (char*) inOverlapped - offsetof(XWinChangeData,fOverlapped));

	xbox_assert( data->GetRefCount() > 0);

	if (!VTask::GetCurrent()->IsDying() && (inBytesTransferred != 0) && (inErrorCode != ERROR_OPERATION_ABORTED) )
	{
		// We have all of the data from a complete event sitting in our buffer.  We need to copy out
		// the data that we care about.  However, we may get more than one notification for a single
		// pass through the loop.  So we need to loop over the result set as well.
		char *bufferptr = (char *)data->fBuffer;
		bool done = false;
		do {
			FILE_NOTIFY_INFORMATION *finfo = (FILE_NOTIFY_INFORMATION *)bufferptr;
			VString fileName;
			fileName.FromBlock( finfo->FileName, finfo->FileNameLength, VTC_UTF_16_SMALLENDIAN );

			// Add the result to the proper vector of results
			data->fThisPointer->AddResultToProperList( data, fileName, finfo->Action );

			// Either advance to the next record, or we're done reporting changes for this folder
			if (finfo->NextEntryOffset) {
				bufferptr += finfo->NextEntryOffset;
			} else {
				done = true;
			}
		} while (!done);

		// Check to see whether we need to create a latency timer or not.  If we don't, we can fire the events
		// manually from here.  But if we have a latency, we need to make a timer to handle it.  If we already
		// have a timer created -- then we need to cancel the old one and reset the new one!
		if (!data->fLatency)
		{
			data->fThisPointer->fOwner->SignalChange( data );
		}
		else if (data->fTimer)
		{
			// We already have a timer, so we want to cancel it -- we'll be resetting it as needed
			::CancelWaitableTimer( data->fTimer );

			// Set the period of the timer to our latency.  Our latency is in milliseconds, but the timer is
			// in 100-nanosecond intervals.  A negative value denotes a relative time, which is what we're interested
			// in.  There are 10,000 100-nanosecond intervals in a millisecond.
			LARGE_INTEGER dueTime = { 0 };
			dueTime.QuadPart = -data->fLatency * 10000;
			::SetWaitableTimer( data->fTimer, &dueTime, 0, TimerProc, (LPVOID)data, FALSE );
		}
		else
		{
			// We should never get here as that means we have a non-zero latency but no timer to fire the events
			xbox_assert( false );
		}

		data->ReadDirectoryChanges();
	}
	data->Release();	// data has been retained by ReadDirectoryChanges()
}
コード例 #9
0
VError VJSONBinaryImporter::GetValue(VJSONValue& outVal)
{
	VError err = VE_OK;
	sBYTE btype = *((uBYTE*)fCurPtr);
	++fCurPtr;
	switch (btype)
	{
		case JSON_null:
			outVal.SetNull();
			break;

		case JSON_undefined:
			outVal.SetUndefined();
			break;

		case JSON_true:
			outVal.SetBool(true);
			break;

		case JSON_false:
			outVal.SetBool(false);
			break;

		case JSON_string:
			{
				VString s;
				sLONG len = *((sLONG*)fCurPtr);
				fCurPtr += 4;
				s.FromBlock(fCurPtr, len * 2, VTC_UTF_16);
				fCurPtr += (len * 2);
				outVal.SetString(s);
			}
			break;

		case JSON_date:
			{
				VTime dd;
				sLONG8 ll = *((sLONG8*)fCurPtr);
				fCurPtr += 8;
				dd.FromMilliseconds(ll);
				outVal.SetTime(dd);
			}
			break;

		case JSON_number:
			{
				Real rr = *((Real*)fCurPtr);
				fCurPtr += sizeof(Real);
				outVal.SetNumber(rr);
			}
			break;

		case JSON_object:
			{
				if (*((sWORD*)fCurPtr) == -2)
				{
					outVal.SetUndefined();
				}
				else
				{
					VJSONObject* obj = new VJSONObject();
					sWORD len;
					do
					{
						len = *((sWORD*)fCurPtr);
						fCurPtr += 2;
						if (len >= 0)
						{
							VString name;
							name.FromBlock(fCurPtr, (sLONG)len * 2, VTC_UTF_16);
							fCurPtr += ((sLONG)len * 2);
							VJSONValue val;
							err = GetValue(val);
							obj->SetProperty(name, val);
						}
					} while (err == VE_OK && len != -1);
					outVal.SetObject(obj);
					QuickReleaseRefCountable(obj);
				}
			}
			break;

		case JSON_array:
			{
				sLONG count = *((sLONG*)fCurPtr);
				fCurPtr += 4;
				if (count == -2)
				{
					outVal.SetUndefined();
				}
				else
				{
					VJSONArray* arr = new VJSONArray();
					for (sLONG i = 0; i < count && err == VE_OK; ++i)
					{
						VJSONValue val;
						err = GetValue(val);
						arr->Push(val);
					}
					outVal.SetArray(arr);
					QuickReleaseRefCountable(arr);
				}
			}
			break;

		default:
			xbox_assert(false);
			break;
	}
	return err;
}
コード例 #10
0
VString XLinuxIntlMgr::GetDateOrTimePattern(Pattern inPatternType) const
{
	icu::DateFormat* dateOrTimeFmt=NULL;

	switch(inPatternType)
	{
	case SHORT_DATE :
	case AM_STRING :	//For AM and PM strings, any SimpleDateFormat should do the job.
	case PM_STRING :
		dateOrTimeFmt=icu::DateFormat::createDateInstance(icu::DateFormat::SHORT, fLocale);
		break;

	case MEDIUM_DATE :
		dateOrTimeFmt=icu::DateFormat::createDateInstance(icu::DateFormat::MEDIUM, fLocale);
		break;

	case LONG_DATE :
		dateOrTimeFmt=icu::DateFormat::createDateInstance(icu::DateFormat::LONG, fLocale);
		break;

	case SHORT_TIME :
		dateOrTimeFmt=icu::DateFormat::createTimeInstance(icu::DateFormat::SHORT, fLocale);
		break;

	case MEDIUM_TIME :
		dateOrTimeFmt=icu::DateFormat::createTimeInstance(icu::DateFormat::MEDIUM, fLocale);
		break;

	case LONG_TIME :
		dateOrTimeFmt=icu::DateFormat::createTimeInstance(icu::DateFormat::LONG, fLocale);
		break;

	default :
		xbox_assert(0);
	}

	xbox_assert(dateOrTimeFmt!=NULL);


	VString pattern;

	if(dateOrTimeFmt!=NULL)
	{
		icu::SimpleDateFormat* simpleDateOrTimeFmt=reinterpret_cast<icu::SimpleDateFormat*>(dateOrTimeFmt);
		xbox_assert(simpleDateOrTimeFmt!=NULL);

		if(simpleDateOrTimeFmt!=NULL)
		{
			if(inPatternType==AM_STRING || inPatternType==PM_STRING)
			{
				//symbols is owned by simpleDateOrTimeFmt - Do not delete it manually !
				const icu::DateFormatSymbols* symbols=simpleDateOrTimeFmt->getDateFormatSymbols();
				xbox_assert(symbols!=NULL);

				if(symbols!=NULL)
				{
					sLONG count=0;
					const UnicodeString* amPmStringArray=symbols->getAmPmStrings(count);

					xbox_assert(count==2);

					if(count==2)
					{
						const UniChar* uniPtr=NULL;
						VSize uniPtrLen=0;

						if(inPatternType==AM_STRING)
							uniPtr=amPmStringArray[0].getBuffer(), uniPtrLen=amPmStringArray[0].length();
						else
							uniPtr=amPmStringArray[1].getBuffer(), uniPtrLen=amPmStringArray[1].length();

						pattern.FromBlock(uniPtr, uniPtrLen*sizeof(UniChar), VTC_UTF_16);
					}
				}
			}
			else
			{
				UErrorCode err=U_ZERO_ERROR;

				UnicodeString tmpPattern;
				simpleDateOrTimeFmt->toLocalizedPattern(tmpPattern, err);
				xbox_assert(err==U_ZERO_ERROR);

				pattern=tmpPattern.getTerminatedBuffer();
				xbox_assert(!pattern.IsEmpty());
			}
		}
	}

	if(dateOrTimeFmt!=NULL)
		delete dateOrTimeFmt;

	return pattern;
}
コード例 #11
0
VError DB4DJournalParser::NextOperation( uLONG8 &outOperation, uLONG8 *outGlobalOperation, CDB4DJournalData **outJournalData )
{
	VError error = VE_OK;
	RecordHeader recHeader;
	
	if ( outJournalData )
		*outJournalData = NULL;

	outOperation = fCurrentOperation;
	sLONG8 globaloperation = 0;
	
	if ( fFileStream )
	{
		uLONG operationTag;
		error = fFileStream->GetLong(operationTag);
		if ( error == VE_OK )
		{
			if ( operationTag == kTagLogDB4D )
			{
				sLONG8 contextID;
				DB4D_LogAction logAction;
				sLONG len;
				sLONG8 curpos;
				error = fFileStream->GetLong8(globaloperation);

				if ( error == VE_OK )
				{
					error = fFileStream->GetLong(len);
				}

				if ( !outJournalData )
				{
					error = fFileStream->SetPosByOffset( len - 24 );//- 4 /*Tag*/ - 8 /*Operation#*/- 4 /*len*/ - 4 /*len at the end*/ - 4 /*tag at the end*/
				}
				else
				{

				if ( error == VE_OK )
					error = fFileStream->GetLong((uLONG&)logAction);

				if ( error == VE_OK )
					error = fFileStream->GetLong8(contextID);

				uLONG8 timeStamp;
				if (error == VE_OK)
					error = fFileStream->GetLong8(timeStamp);


				if (error == VE_OK)
				{
					switch (logAction)
					{
						case DB4D_Log_OpenData:
						case DB4D_Log_CloseData:
						case DB4D_Log_StartBackup:
						case DB4D_Log_StartTrans:
						case DB4D_Log_Commit:
						case DB4D_Log_RollBack:
							{
								*outJournalData = new VDB4DJournalData(globaloperation, logAction,contextID, GetContextExtraData( contextID),timeStamp);
							}
							break;

						case DB4D_Log_CloseContext:
							{
								*outJournalData = new VDB4DJournalData(globaloperation, logAction,contextID, GetContextExtraData( contextID),timeStamp);
								fContextExtraByID.erase(contextID);
							}
							break;

						case DB4D_Log_CreateRecord:
						case DB4D_Log_ModifyRecord:
							{
								VUUID xTableID;
								if ( error == VE_OK )
									error = recHeader.ReadFromStream(fFileStream);
								
								if ( error == VE_OK )
									if ( !recHeader.Match(DBOH_Record) )
										error = VE_DB4D_WRONGRECORDHEADER;
								
								if ( error == VE_OK )
									error = xTableID.ReadFromStream(fFileStream);

								curpos = fFileStream->GetPos();
								if ( error == VE_OK )
								{
									sLONG dataSize = recHeader.GetLen() + sizeof(ChampHeader)*(recHeader.GetNbFields());
									error = fFileStream->SetPosByOffset(dataSize);
								}
								if ( error == VE_OK )
									*outJournalData = new VDB4DJournalData(globaloperation, logAction,contextID, GetContextExtraData( contextID),&recHeader,timeStamp, curpos, fFileStream, xTableID);
							}
							break;

						case DB4D_Log_DeleteBlob:
							{
								VString path;
								sLONG blobnumber;
								if ( error == VE_OK )
									error = fFileStream->GetLong(blobnumber);

								if (blobnumber == -2)
								{
									sLONG lenpath = 0;
									error = fFileStream->GetLong(lenpath);
									if (lenpath > 0)
									{
										tempBuffer<256> buff(len);
										error = fFileStream->GetWords((sWORD*)buff.GetPtr(), &lenpath);
										path.FromBlock(buff.GetPtr(), lenpath * sizeof(UniChar), VTC_UTF_16);
									}
								}
								
								VUUID xTableID;
								if ( error == VE_OK )
									error = xTableID.ReadFromStream(fFileStream);

								if ( error == VE_OK )
								{
									VDB4DJournalData* jdata = new VDB4DJournalData(globaloperation, logAction,contextID, GetContextExtraData( contextID),timeStamp, blobnumber ,xTableID);
									*outJournalData = jdata;
									if (!path.IsEmpty())
									{
										jdata->SetPath(path);
									}
								}
							}
							break;

						case DB4D_Log_DeleteRecord:
						case DB4D_Log_TruncateTable:
							{
								sLONG recordNumber;
								if ( error == VE_OK )
									error = fFileStream->GetLong(recordNumber);
								/*
								sLONG tableIndex;
								if ( error == VE_OK )
									error = fFileStream->GetLong(tableIndex);
								*/
								VUUID xTableID;
								if ( error == VE_OK )
									error = xTableID.ReadFromStream(fFileStream);

								if ( error == VE_OK )
									*outJournalData = new VDB4DJournalData(globaloperation, logAction,contextID, GetContextExtraData( contextID),timeStamp,recordNumber,xTableID);
							}
							break;

						case DB4D_Log_CreateContextWithUserUUID:
							{
								VUUID userID;
								error = userID.ReadFromStream(fFileStream);
								if (error == VE_OK)
									*outJournalData = new VDB4DJournalData(globaloperation, logAction,contextID, GetContextExtraData( contextID),timeStamp,userID);
							}
							break;
						
						case DB4D_Log_CreateContextWithExtra:
							{
								VValueBag *bag = new VValueBag;
								if (bag != NULL)
								{
									// the extra data is always stored in little endian
									Boolean oldNeedSwap = fFileStream->NeedSwap();
									fFileStream->SetLittleEndian();
									error = bag->ReadFromStream(fFileStream);
									fFileStream->SetNeedSwap( oldNeedSwap);
									
									if (error == VE_OK)
									{
										try
										{
											fContextExtraByID[contextID] = bag;
										}
										catch(...)
										{
										}
										*outJournalData = new VDB4DJournalData(globaloperation, logAction,contextID, GetContextExtraData( contextID),timeStamp);
									}
								}
								else
								{
									error = memfull;
								}
								ReleaseRefCountable( &bag);
							}
							break;

						case DB4D_Log_CreateBlob:
						case DB4D_Log_ModifyBlob:
							{
								VString path;

								sLONG lenblob = 0;
								sLONG blobNumber;
								if ( error == VE_OK )
									error = fFileStream->GetLong(blobNumber);

								if (blobNumber == -2)
								{
									sLONG lenpath = 0;
									error = fFileStream->GetLong(lenpath);
									if (lenpath > 0)
									{
										tempBuffer<256> buff(len);
										error = fFileStream->GetWords((sWORD*)buff.GetPtr(), &lenpath);
										path.FromBlock(buff.GetPtr(), lenpath * sizeof(UniChar), VTC_UTF_16);
									}
								}


								VUUID xTableID;
								if ( error == VE_OK )
									error = xTableID.ReadFromStream(fFileStream);

								curpos = fFileStream->GetPos();
								if ( error == VE_OK )
								{
									error = fFileStream->GetLong(lenblob);
									error = fFileStream->SetPosByOffset(lenblob);
								}
								if ( error == VE_OK )
								{
									VDB4DJournalData* jdata = new VDB4DJournalData(globaloperation, logAction,contextID, GetContextExtraData( contextID),timeStamp, blobNumber, lenblob, xTableID, curpos, fFileStream);
									*outJournalData = jdata;
									if (!path.IsEmpty())
									{
										jdata->SetPath(path);
									}
								}
							}
							break;

						case DB4D_Log_SaveSeqNum:
							{
								sLONG8 seqnum;
								if ( error == VE_OK )
									error = fFileStream->GetLong8(seqnum);
								/*
								sLONG tableIndex;
								if ( error == VE_OK )
								error = fFileStream->GetLong(tableIndex);
								*/
								VUUID xTableID;
								if ( error == VE_OK )
									error = xTableID.ReadFromStream(fFileStream);

								if ( error == VE_OK )
									*outJournalData = new VDB4DJournalData(globaloperation, logAction,contextID, GetContextExtraData( contextID), timeStamp, seqnum, xTableID, true);
							}
							break;

						default:
							assert(false);
							break;
					}
				}
				}
				sLONG lenEnd;
				if ( error == VE_OK )
				{
					error = fFileStream->GetLong(lenEnd);
					if (len != lenEnd)
						error = VE_UNIMPLEMENTED;
				}

				uLONG operationTagEnd;
				if (error == VE_OK)
				{
					error = fFileStream->GetLong((uLONG&)operationTagEnd);
					if (operationTagEnd != kTagLogDB4DEnd)
						error = VE_UNIMPLEMENTED;
				}
			}
			else
			{
				error = VE_UNIMPLEMENTED; // bad file
			}

			if ( error != VE_OK )
			{
				if ( outJournalData && *outJournalData )
				{
					(*outJournalData)->Release();
					*outJournalData = NULL;
				}
			}
			else
			{
				outOperation = ++fCurrentOperation;
				if ( outJournalData && *outJournalData )
				{
					if ( fCurrentData )
						fCurrentData->Release();
					fCurrentData = *outJournalData;
					fCurrentData->Retain();
				}
			}
		}
	}
	else
	{
		error = VE_UNIMPLEMENTED; // not initialized
	}

	if (outGlobalOperation != NULL)
		*outGlobalOperation = globaloperation;
	
	return error;
}
コード例 #12
0
ファイル: VFont.cpp プロジェクト: sanyaade-iot/core-XToolbox
/** return the best existing font family name which matches the specified generic ID 
@see
	eGenericFont
*/
void VFont::GetGenericFontFamilyName(eGenericFont inGenericID, VString& outFontFamilyName, const VGraphicContext *inGC)
{
#if VERSIONWIN
	const Gdiplus::FontFamily *fontFamily = NULL;
	switch( inGenericID)
	{
	case GENERIC_FONT_SERIF:
		fontFamily = Gdiplus::FontFamily::GenericSerif();
		break;
	case GENERIC_FONT_SANS_SERIF:
		fontFamily = Gdiplus::FontFamily::GenericSansSerif();
		break;
	case GENERIC_FONT_CURSIVE:
		//gdiplus implementation constraint: 
		//try with "Comic Sans MS"
		//and if failed fallback to sans-serif
		{
			if (FontExists( "Comic Sans MS", KFS_NORMAL, 12, 0, inGC))
			{
				outFontFamilyName = "Comic Sans MS";
				return;
			}
			fontFamily = Gdiplus::FontFamily::GenericSansSerif();
		}
		break;
	case GENERIC_FONT_FANTASY:
		//gdiplus implementation constraint: fallback to sans-serif
		fontFamily = Gdiplus::FontFamily::GenericSansSerif();
		break;
	case GENERIC_FONT_MONOSPACE:
		fontFamily = Gdiplus::FontFamily::GenericMonospace();
		break;
	default:
		xbox_assert(false);
		fontFamily = Gdiplus::FontFamily::GenericSansSerif();
		break;
	}
	if (fontFamily && fontFamily->IsAvailable())
	{
		WCHAR  name[LF_FACESIZE];
		Gdiplus::Status status = fontFamily->GetFamilyName( name, LANG_NEUTRAL);
		xbox_assert(sizeof(WCHAR) == sizeof(UniChar));
		outFontFamilyName.FromBlock( name, wcslen( name)*sizeof(UniChar), VTC_UTF_16);
	}
	else
		outFontFamilyName = "Times New Roman";
#if ENABLE_D2D
#if VERSION_DEBUG
	//check if font family is supported by DWrite too
	//(should always be the case because GDIPlus has support only for TrueType fonts
	// & all TrueType fonts are supported by D2D)
	if (VWinD2DGraphicContext::IsAvailable())
	{
		if (inGC && inGC->IsD2DImpl())
			xbox_assert(FontExists( outFontFamilyName, KFS_NORMAL, 12, inGC));
	}
#endif
#endif
#else
	//MAC OS implementation constraint:
	//as there is no system-provided feature that can feed us with generic fonts
	//(of course if you know about such a feature feel free to modify code below)
	//we need to provide ourselves generic font family names
	//so we choose to use font family names that are always installed on MAC OS X

	VString fontFamily;
	switch( inGenericID)
	{
	case GENERIC_FONT_SERIF:
		fontFamily = "Times New Roman";
		break;
	case GENERIC_FONT_SANS_SERIF:
		fontFamily = "Helvetica";
		break;
	case GENERIC_FONT_CURSIVE:
		fontFamily = "Apple Chancery";
		break;
	case GENERIC_FONT_FANTASY:
		fontFamily = "American Typewriter";
		break;
	case GENERIC_FONT_MONOSPACE:
		fontFamily = "Courier New";
		break;
	default:
		xbox_assert(false);
		fontFamily = "Times New Roman";
		break;
	}
	if (FontExists( fontFamily, KFS_NORMAL, 12))
		outFontFamilyName = fontFamily;
	else
		//fallback to "Times Roman" just in case...
		outFontFamilyName = "Times New Roman";
#endif
}