Sunday, August 3, 2008

Monday, May 26, 2008

Live cash back --- A game changer?

Microsoft Live Search cash back definitely has caught a lot of eyeballs. There are lots of discussions on the Internet, mostly, about how Microsoft is trying to buy in customers to use live search. However, look a little further behind the scene, we will see this is not just about another type of "rebate".
Google didn't invent search, they invented pay-per-click advertisement. This game changing invention has brought them billions and billions of dollars and will continue to be their cash cow for a while. While pay-per-click advertisement has significantly reduced the advertisement risk because you don't have to pay for a badly placed key work because people simply won't click them, it does not grantee that people who clicked the ad will eventually buy the product. this kind of risk can be eliminated by a new type of advertisement : pay-per-action.
Many websites have tried this idea before, some of them are actually very successful, http://rebate.com/ is an example. For most of them, the number one problem is still, search. Customers need to find their product first. So the first step of game is still search. Microsoft live search still need to improve search to get the chance to change the game. At this point, however, seems Google is still leading the game at a firm No.1 position.

Wednesday, April 23, 2008

pc/tc for gdb

It would be nice if we can have the equivalent of windbg's pc and tc command in gdb, well, here is how:

def pc

set $continue_flag = 1

ni

while($continue_flag)

set $opcode = *(unsigned char *)$pc

x/i $pc

if ((unsigned int)$opcode == 0xe8)

set $continue_flag = 0

else

ni

end

end

end


def tc

si

set $continue_flag = 1

while($continue_flag)

set $opcode = *(unsigned char *)$pc

x/i $pc

if ((unsigned int)$opcode == 0xe8)

set $continue_flag = 0

else

si

end

end

end

Friday, March 28, 2008

Wednesday, March 26, 2008

Looking for "strace" for windows?

This one is windows' equivalent of linux's strace:
http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx

Sunday, March 9, 2008

System Call Argument Passing

X86:

Windows:
The system call number is passed in the EAX register, and the stack stores the caller arguments.

Linux:
http://manugarg.googlepages.com/systemcallinlinux2_6.html

X64:

Windows:
A system-call is done via the syscall instruction. Parameters are passed by %rcx,%rdx, %r8 and %r9, the rest are passed on stack.

Linux:
A system-call is done via the syscall instruction. Parameters are passed by %rdi,%rsi, %rdx, %r10, %r8 and %r9.The kernel destroys
registers %rcx and %r11.

Saturday, February 16, 2008

How to run CMD.exe as localsystem

sc create testsvc type= own binpath= "cmd /c start c:\debuggers\remote /s cmd localsys"
sc start testsvc
sc delete testsvc
[Windows_Debugging_Tools_Dir]\remote /c . localsys

Friday, February 15, 2008

How to trace function enter and exit


class FuncEnterExitTracer{
private:
LPCWSTR m_functionName;
public:
FuncEnterExitTracer(LPCWSTR functionName)
: m_functionName(functionName) {
TRACE(L"Entering: %s\n...", m_functionName);
}

~FuncEnterExitTracer() {
TRACE(L"Exiting: %s\n...", m_functionName);
}
};

#define TRACE_FUNC_ENTER_EXIT() FuncEnterExitTracer autoVariable (TEXT(__FUNCTION__))




Now in any function, you can use TRACE_FUNC_ENTER_EXIT(); to trace enter and exit:

void AnyFunc(int p1, ...)

{

TRACE_FUNC_ENTER_EXIT();

....................

}

Tuesday, February 12, 2008

How to get the current apartment for a thread

0:004> !teb

TEB at 7ffda000

......

0:004> dt TEB 7ffda000 ReservedForOle

ntdll!TEB

+0xf80 ReservedForOle : 0x001ff650

0:004> dt SOleTlsData 0x001ff650

ole32!SOleTlsData

......

+0x030 pObjServer : (null)

+0x034 dwTIDCaller : 0

+0x038 pCurrentCtx : 0x001cb7a8 CObjectContext

+0x03c pEmptyCtx : (null)

......

+0x080 LogicalThreadId : _GUID {6cb93bfd-eb78-4a9d-8537-91de9ea8b38f}

+0x090 hThread : 0x0000019c

+0x094 hRevert : (null)

......

+0x108 incomingCallData : tagIncomingCallData

+0x10c outgoingActivationData : tagOutgoingActivationData

0:004> dt CObjectContext 0x001cb7a8

ole32!CObjectContext

......

+0x040 _MarshalSizeMax : 0

+0x044 _pApartment : 0x001ec908 CComApartment

+0x048 _dwHashOfId : 6

......


0:004> dt -r2 CObjectContext 0x001cb7a8

ole32!CObjectContext

......

+0x008 _dwState : 3

+0x00c _AptKind : 2 ( APTKIND_MULTITHREADED )

+0x010 _AptId : 0

......

Now let's put them into one single command:

dt ole32!CComApartment poi(@@C++(#FIELD_OFFSET(ole32!CObjectContext,_pApartment))+poi(poi($thread+@@C++(#FIELD_OFFSET(kernel32!TEB, ReservedForOle)))+@@C++(#FIELD_OFFSET(ole32!SOleTlsData,pCurrentCtx))))))

Friday, January 11, 2008

the power of presentation

Data visualization has long been a hot research topic, but I have never seen any one done this before:

http://www.ted.com/index.php/talks/view/id/92

Friday, January 4, 2008

A common no-throw problem in Java and C# samples on the Internet

I guess no-throw is a term used by C++ gurus, but it is also applicable to some Java or .NET applications. for example, I have seen a lot of database connection samples floating on the Internet, unfortunately, most of them are wrong:
here is a example from MSDN: http://msdn2.microsoft.com/en-us/library/ms228366(VS.80).aspx


// Sample C# code accessing a sample database

// You need:
// A database connection
// A command to execute
// A data adapter that understands SQL databases
// A table to hold the result set

namespace DataAccess
{
using System.Data;
using System.Data.SqlClient;

class DataAccess
{
//This is your database connection:
static string connectionString = "Initial Catalog=northwind;Data Source=(local);Integrated Security=SSPI;";
static SqlConnection cn = new SqlConnection(connectionString);

// This is your command to execute:
static string sCommand = "SELECT TOP 10 Lastname FROM Employees ORDER BY EmployeeID";

// This is your data adapter that understands SQL databases:
static SqlDataAdapter da = new SqlDataAdapter(sCommand, cn);

// This is your table to hold the result set:
static DataTable dataTable = new DataTable();

static void Main()
{
try
{
cn.Open();

// Fill the data table with select statement's query results:
int recordsAffected = da.Fill(dataTable);

if (recordsAffected > 0)
{
foreach (DataRow dr in dataTable.Rows)
{
System.Console.WriteLine(dr[0]);
}
}
}
catch (SqlException e)
{
string msg = "";
for (int i=0; i < e.Errors.Count; i++)
{
msg += "Error #" + i + " Message: " + e.Errors[i].Message + "\n";
}
System.Console.WriteLine(msg);
}
finally
{
if (cn.State != ConnectionState.Closed)
{
cn.Close();
}
}
}
}
}



Looks like we have covered any possible problem by using try-catch-finally, but there is one place which might give us a surprise, especially in production system:




            finally
{
if (cn.State != ConnectionState.Closed)
{
cn.Close();
}
}



If cn is in a broken state, cn.Close() will throw a Exception, which might be a surprise because nobody is catching it. A better way to make sure the connection resource is released should be:



            finally
{
if (cn.State != ConnectionState.Closed)
{
try{
cn.Close();
}catch (Exception ex)
{
//nothing we can do here, but we don't want a surprise
}
}
}



which looks ugly, but works. Fortunately, C# has a better way to write this, which is correctly documented in SqlConnection online document:

http://msdn2.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.close.aspx


private static void OpenSqlConnection(string connectionString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
Console.WriteLine("ServerVersion: {0}", connection.ServerVersion);
Console.WriteLine("State: {0}", connection.State);
}
}


For Java, we are not luckier, a lot of samples have the same problem, you can Google out dozens of them.

In general, it is always a good practice to make sure no-throw in finally block in .NET or Java.

Tuesday, January 1, 2008

BitOperations --- What do you think SomeFunction does?

int SomeFunction(int* intArr, int numElements)
{
int bytesNeed = numElements/8 + 1;
char* buf = new char[bytesNeed];
for(int i=0; i<bytesNeed; i++)
{
buf[i] = (unsigned char)0x0;
}

for (int j=0; j<numElements; j++)
{
int byteOffset = intArr[j]/8;
int bitOffset = intArr[j]%8;
if (bitOffset == 0)
{
byteOffset = byteOffset -1;
unsigned short check = buf[byteOffset] & 0x1;
if (check == 1)
{
return 1;
}
else
{
buf[byteOffset] = buf[byteOffset] 0x1;
}
}
else
{
unsigned char check = buf[byteOffset] >> (8-bitOffset);
check = check & 0x1;
if ((int)check == 1)
{
return 1;
}
else
{
buf[byteOffset] = buf[byteOffset](0x1 << (8-bitOffset));
}

}

}
return 0;
}