Click here to Skip to main content
Click here to Skip to main content

Generate PDB files in C#

By , 10 Jan 2006
 

PDB Generator

Basics of Palm databases

Palm devices use two types of database files: PRC and PDB (i.e., .prc and .pdb). PRC is used for Palm OS databases that are application programs, and stores resources of the application, while the PDB (Pilot Database) is used for Palm OS databases that contain only data. Both databases have a unique key that is unique for each application. These databases can be manipulated like stream reading and stream writing. It contains an attribute bit called the Backup Bit. Setting this bit indicates that no custom conduit will be backing up the database and that the database should be backed up during the HotSync process. If you create a database on the Palm Pilot and set the Backup Bit, you will find a copy of the database in PDB format in the Backup directory on the computer with which the HotSync was performed.

This application reads a CSV or an XML file and creates a .pdb file.

Major Sections of the PDB File

A PDB file format contains three sections:

  1. Header section
  2. Recordlist section
  3. Datalist section

i. Header Section

The header section contains 78 bytes, containing the name of the database and other information. Also, contained is the ID of the database that is unique for an application (the ID is globally unique, and can be obtained from the Palm OS site), the type of the database, and other attributes. The PDBHeader class is used to create headers.

class PDBHeader
{
    #region Declarations
    char[] databaseName={'\0','\0','\0','\0','\0','\0','\0', 
                         '\0','\0','\0','\0','\0','\0','\0','\0',
                         '\0','\0','\0','\0','\0','\0','\0','\0',
                         '\0','\0','\0','\0','\0','\0','\0',
                         '\0','\0'};   // 32 Bytes

    UInt16 fileAttributes = 0X0008;    // 2 Bytes
    UInt16 version = 0X0000;           // 2 Bytes
    UInt32 creationDate;               // 4 Bytes
    UInt32 modificationDate;           // 4 Bytes
    UInt32 lastBackupDate;             // 4 Bytes
    UInt32 modification=0X0000;        // 4 Bytes
    UInt32 appInfoArea=0X0000;         // 4 Bytes
    UInt32 sortInfoArea=0X0000;        // 4 Bytes
    char[]  type={'d','a','t','a'};    // 4 Bytes
    char[]  creatorID;                 // 4 Bytes
    UInt32 uniqueID=0X0000;            // 4 Bytes
    UInt32 nextRecord=0X0000;          // 4 Bytes
    UInt16 numRecords;                 // 2 Bytes
    #endregion 

    #region Properties
    public UInt16 NumRecords
    {
        set
        {
            numRecords=value;
        }
        get
        {
            return numRecords;
        }
    }
    public DateTime CreationDate
    {
        set
        {
            TimeSpan ts=DateTime.Now-value;
            creationDate=(UInt32)ts.TotalSeconds;
        }
    }
    public DateTime ModificationDate
    {
        set
        {
            TimeSpan ts=DateTime.Now-value;
            modificationDate=(UInt32)ts.TotalSeconds;
        }
    }
    public DateTime LastBackupDate
    {
        set
        {
            TimeSpan ts=DateTime.Now-value;
            lastBackupDate=(UInt32)ts.TotalSeconds;
        }
    }

    public string CreatorID
    {
        set
        {
            if (value.Length==4)
            {
                creatorID=value.ToCharArray();
            }
            else
            {
                throw new PDBException("Creator ID" + 
                  " is invalid (must be 4 charactors)");;
            }
        }
        get
        {
            return new String(creatorID);
        }
    }

    public string DataBaseName
    {
        set
        {
            if (value.Length<=32)
            {
                databaseName=value.ToCharArray();
            }
            else
            {
                
                throw new PDBException("Database Name" + 
                             " Exceeds 32 Charactors");;
            }
        }
        get
        {
            return new String(databaseName);
        }
    }

    #endregion 

    #region Functions

    public PDBHeader()
    {
        // Palm databse store total number
        // of seconds since 01-01-1904
        TimeSpan ts=
          DateTime.Now-DateTime.Parse("01-01-1904");
        creationDate=(UInt32)ts.TotalSeconds;
        modificationDate=(UInt32)ts.TotalSeconds;
        lastBackupDate=(UInt32)ts.TotalSeconds;
        numRecords=0;
    }

    public override string ToString()
    {
        string getAll="";
        getAll+=HexEncoding.GetStringToChar(databaseName,32);
        getAll+=fileAttributes.ToString("X4");
        getAll+=version.ToString("X4");
        getAll+=creationDate.ToString("X8");
        getAll+=modificationDate.ToString("X8");
        
        
        getAll+=lastBackupDate.ToString("X8");        
        getAll+=modification.ToString("X8");
        getAll+=appInfoArea.ToString("X8");    
        getAll+=sortInfoArea.ToString("X8");
        getAll+=HexEncoding.GetStringToChar(type,4);
        getAll+=HexEncoding.GetStringToChar(creatorID,4);
        getAll+=uniqueID.ToString("X8");
        getAll+=nextRecord.ToString("X8");
        getAll+=numRecords.ToString("X4");

        return getAll;
    }

ii. RecordList Section

The size of the recordlist section depends on the number of records. Each record uses 8 bits to store record information. The PDBRecordList class is used to represent a recordlist.

class PDBRecordList
{
    #region Declarations
    UInt32 offset=0;   // 4 Bytes (Offset of the record)
    byte recordAttribute=0X40;
    char[] uniqueID={'\0','\0','\0'}; // 3 Bytes (Unique ID for each record)
    string dataRecord=""; // Record data for current record
    #endregion 

    #region Properties
    public string DataRecord
    {
        set
        {
            dataRecord=value;
        }
        get
        {
            return dataRecord;
        }
    }
    public UInt32 RecordOffset
    {
        set
        {
            offset=value;
        }
        get
        {
            return offset;
        }
    }
    #endregion 

    #region Functions
    public PDBRecordList(string str)
    {
        dataRecord=str;
    }
    public override string ToString()
    {

        string getAll="";
        getAll+=offset.ToString("X8");
        getAll+=recordAttribute.ToString("X2");        
        getAll+=HexEncoding.GetStringToChar(uniqueID,3);
        return getAll;
    }

    #endregion
}

iii. Data Section

It is the main section to store information related to the records. Each record is separated by a null terminated character ('\0'). The size of each record may vary but the number of columns should be the same.

Using the code

The PDBCreators class is used to create databases.

class PDBCreators
{
    PDBHeader header=new PDBHeader();
    ArrayList pdbRecord=new ArrayList();
    public PDBCreators()
    {
    }
    public PDBHeader PDBHeaders
    {
        set
        {
            header=value;
        }
        get
        {
            return header;
        }
    }
    public Object[] AddRecord
    {
        set
        {
            string row="";
            for (int i=0; i<value.Length; i++)
            {
                if (value[i].GetType().ToString()=="System.Int32")  
                    continue;
                row+=value[i].ToString().Trim()+'\0';
            }
            pdbRecord.Add(new PDBRecordList(row));
        }
    }

    public void GeneratePDB(string fileName)
    {
        try
        {
            FileStream fs=new FileStream(fileName,FileMode.Create);
            BinaryWriter bw=new BinaryWriter(fs);
            int discard=0;
            UInt32 index=78;     // Header length is 78 Bytes
            header.NumRecords=(UInt16)pdbRecord.Count;

            bw.Write(HexEncoding.GetBytes(header.ToString(), 
                                              out discard));

            // start index of Data List Area
            index+=(UInt32)(pdbRecord.Count*8)+2;
            string result="";
            for (int i=0; ipdbRecord.Count; i++)
            {
                PDBRecordList rec=(PDBRecordList)pdbRecord[i];
                rec.RecordOffset=index;
                bw.Write(HexEncoding.GetBytes(rec.ToString(), 
                                               out discard));
                index+=(UInt32)rec.DataRecord.Length;
                result+=rec.DataRecord;
            }
            char[] padding={'\0','\0'};  // Two bytes for backup bits
            bw.Write(HexEncoding.GetBytes(
              HexEncoding.GetStringToChar(padding,2), 
              out discard));
            result=HexEncoding.GetStringToChar(
              result.ToCharArray(),result.Length);
            bw.Write(HexEncoding.GetBytes(result,out discard));
            bw.Close();
            fs.Close();
        }
        catch (Exception exc)
        {
            throw new PDBException("Error" + 
              " in writing pdb file "+exc.Message);
        }

    }
}

The PDBGenerator reads two file formats (CSV and XML) and displays data in table format in a DataGrid. This data can be changed. It reads all table data from the XML file and displays table names in a combo box.

PDBCreators pdb=new PDBCreators();
pdb.PDBHeaders.DataBaseName=this.txtDBName.Text;
pdb.PDBHeaders.CreatorID=this.txtCreatorID.Text;

DataTable recordsTable;
if (recordsDataSet.Tables.Count>0 && 
        this.cmbTableNames.Items.Count>0 && 
        recordsDataSet.Tables.Contains(this.cmbTableNames.Text))
    recordsTable=recordsDataSet.Tables[this.cmbTableNames.Text];
else
{
    MessageBox.Show("There is no table to convert", 
          "PDB Generator",MessageBoxButtons.OK,
          MessageBoxIcon.Information);
    return;
}
for (int i=0; i<recordsTable.Rows.Count; i++)
    pdb.AddRecord=recordsTable.Rows[i].ItemArray;
try
{
    pdb.GeneratePDB(this.txtDestination.Text+"\\"+
                      this.txtDBName.Text+".pdb");
    MessageBox.Show("PDB Generated Successfully",
      "PDB Generator",MessageBoxButtons.OK,
      MessageBoxIcon.Information);
}
catch(Exception exc)
{
    MessageBox.Show("Error in PDB Generation"+exc.ToString(),
      "PDB Generator",MessageBoxButtons.OK,
      MessageBoxIcon.Information);
}

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)

About the Author

MRSumra
Web Developer
Pakistan Pakistan
Member
I'm working as Software Engineer at ISF (Islamabad Software Factory) in Pakistan and involves in multiple products having different languages in different phases. My favourite areas are PDA's, Palm's, .Net and webservices......

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Generalrle compression of contentmemberUnruled Boy27 Nov '09 - 22:58 
the actual content of a standard pdb file is compressed with RLE algo. any idea?
 
Regards,
unruledboy_at_gmail_dot_com
http://www.xnlab.com
modified on Saturday, November 28, 2009 8:25 PM

GeneralNice, but the PDB generated can't be read by my application.memberMember 45957942 Jul '08 - 5:56 
Hello,
 
I don't understand why, but I can't retrieved the data from the PDB generated with my application.
(POCKET PC with a processor MIPS).
 
The PDB can be open but, the data can't be accessed.
 
Dead | X|
 
I'm sure my pocket application works, 'cause I can access PDB generated in java.
 
But I try to migrate the java application to C#.
 
the last things to be done is to create the PDB in C#, please help me !
GeneralRe: Nice, but the PDB generated can't be read by my application.memberMRSumra2 Jul '08 - 19:14 
First, try to simple pdb file with less data (one or two records),
and do proper logging to diagnose the actual problem.
 
Muhammad Rizwan Sumra

GeneralRe: Nice, but the PDB generated can't be read by my application.memberMember 45957944 Jul '08 - 4:06 
Thanks for your reply.
 
This is the PDB generated with 2 lines from an XML file.
I can't read them from my pocket application cause when I parse it I never find anythiing.
 
BDPKAMAX  Ä“úÄ“úÄ“ú DATAHEBD  p@ v@ |@ @ A 1 D 1 D GABELLA 1,2 3630 A JEAN (A) 1,2 3631
GeneralRe: Nice, but the PDB generated can't be read by my application.memberMember 45957948 Jul '08 - 4:22 
I works under eclipse in a java application to parse the pdb.
 
The header seems to be ok, but the data area doesn't work.
The number of data is correct, but when I try to pop one I have a very long string with nothing inside, and this for the 4 datas store in.
Generalpdb usememberMember 23874258 Apr '08 - 2:57 
i have developing one application related sales for palm
using superwaba platform
now using your project when i create pdb same with creater id and database name as per i can use in my apps from csv
(item name, item code,item description, item price)
data in csv like
Tea TT TEst1 12.00
cofee CC Test2 23.00
 
and read in my apps using superwaba grid it shows an some numbers in first rows inspite of data
i could not understand why?
please help me if you catch me
Confused | :confused:
GeneralRe: pdb usememberMRSumra9 Apr '08 - 0:17 
can you send me the exact csv files that you want to port?
 
Muhammad Rizwan Sumra

GeneralRe: pdb usememberMember 23874259 Apr '08 - 3:02 
thanks
there is no attachement option so i have give you some records using thread
 
CAD-1-1-1,CADBURY DAIRY MILK MONEY SEVER SVP,35,30.5,1,N
CAD-2-1-1,CADURY DAIRY MILK 165GM(NO),65,55.3,1,N
CAD-3-1-1,CADBURY DAIRY MILK RS 5/-,5,4.4,1,N
CAD-4-1-1,CADBURY DAIRY MILK 12GM POPPER(NO),6,5.24,1,N
CAD-5-1-1,CADBURY DAIRY MILK RS 5/- 2 IN 1,5,4.37,1,N
CAD-6-1-1,CADBURY DAIRY MILK 24 GMRS 10/-,10,8.75,1,N
CAD-7-1-1,CADBURY DAIRY MILK 40GMRS 17/-,16,13.9,1,N
CAD-8-1-1,CADBURY DAIRY MILK CHUNKY 42 GM(NO),16,13.99,1,N
CAD-9-1-1,CADBURY DAIRY MILK 42GM2IN 1(NO),16,13.99,1,N
CAD-10-1-1,CADBURY DAIRY MILK 12GM*24 UNIT(NO),5,4.37,1,N
CAD-11-1-1,CADBURY DAIRY MILK 12GM*40UNIT(NO),5,4.37,1,N
CAD-12-1-1,CADBURY DAIRY MILK 95GM CARTON(NO),42,36.06,1,N
CAD-13-1-1,BOURNVILLE DARK 44 GM(NO),20,17.17,1,N
CAD-14-1-1,FRUIT &NUT 44GMFLOWPACK(NO),28,24.5,1,N
CAD-15-1-1,FRUIT &NUT 80GM(NO),45,38.63,1,N
CAD-16-1-1,ROST ALMOND 44GM(NO),26,20.75,1,N
CAD-17-1-1,ROST ALMOND 80 GM(NO),45,38.63,1,N
CAD-18-1-1,MILK TREAT CREAMY 13GM,5,4.15,1,N
CAD-19-1-1,MILK TREAT CREAMY 26GM 13*2(NO),10,8.74,1,N
CAD-20-1-1,TEMPATINOS 72GM*15UNIT(OA+AT)(NO),45,36.06,1,N
CAD-20-2-1,TEMPATINOS 72GM*15UNIT(OA+AT)(NO),42,36.06,1,N
CAD-21-1-1,CRACKLE 160GM(NO),75,64.39,1,N
CAD-22-1-1,CRACKLE 42GM FLOEPACK(NO),20,17.17,1,N
 

in this Header is (string itemid,string itemname,double mrp,double rate,int rate per,string issim)
 
i have writen header with datatype because it is used in programming of superwaba
 
Actually my try is that using your code reference i want to create pdb using vb because my desktop application works on vb
 
thanks
GeneralRe: pdb usememberMRSumra9 Apr '08 - 6:49 
csv seems fine.
Try to put first simple data like A,a,b,c,1,2,3,4 and check is this readable in your device or not
and let me know if you have some findings.
 
Muhammad Rizwan Sumra

GeneralRe: pdb usememberMember 45957948 Jul '08 - 4:30 
I have the same problem and I use, too, superwaba tools to read the pdb.
 
Did you find an issue to your problem ?
GeneralDoes not seem to work.memberMurdocMA25 Jun '07 - 5:32 
Am I doing something wrong??
 
I've taken your compiled demo, and your source files, run the application and the output file appears to not be valid, I've tried PDB Exploerer (which I've used many times and usually has no trouble opening PDB files) I also tried using PDAT/DB application on a palm pilot and the output file appears to be corrupt?
 
Thanks in advance!... from other people's comments it's possible I'm doing something wrong.. I don't have Visual C# installed, so I'm just using the demo compiled app, and your source test.csv.
 
I work in VB.net mostly.. so if anyone has a working version I'd apreciate it!

GeneralRe: Does not seem to work.memberrobertoy28 Sep '07 - 5:21 
I have a working version of it on VB.net, I converted it. However remember in .Net you can mix languages
QuestionRe: Does not seem to work.memberneal0071 Oct '07 - 11:11 
Hello,
 
Can you send me the VB.NET source please? Please send to neal AT nc-software DOT com.
 
Thank you.
 
Neal Culiner
President, NC Software, Inc.

QuestionSync PDB and SQL Server 2005memberHandyGuy15 Jun '07 - 9:45 
Hi dude nice article....Smile | :) , currently I am working on mobile application development using compact framework 2.0 and MS-SQL Server 2005, my requirement is I have few pdb ( Palm OS Database) files in a shared folder of a file server , I need to read the pdb file and dump the data into MS-SQL Server 2005 can you please let me know how to do it or is SQL replication possible ? if so let me know how to do it.

GeneralPDB record headermembermihasic3 May '07 - 2:39 
once i found these struct (it may descript attributes field, but i'm not sure if it's correct, because of error in pdb_header.attributes field size)
// C++
struct pdb_rec_header { /* 8 bytes total */
DWord offset;
struct {
int delete : 1;
int dirty : 1;
int busy : 1;
int secret : 1;
int category : 4;
} attributes;
char uniqueID[3];
}

source
GeneralAnd PDB to XMLmemberjohatenxxx7 Mar '07 - 11:27 
Cry | :(( Please de inverse Process?
GeneralRead writememberpablojag2 Aug '06 - 6:33 
Anything new on reading PDB files from Net Framework?
 
Thx in advance
 
Take care of your ideas, they can come real

GeneralRe: Read writememberjulgui12 Sep '06 - 23:29 
Hi,
 
I am also interested on this.
 
Are you still working in how to read PDB files? Do you still plan to release the code?
 
In any case, thanks for a very good article.

Questionwhat does padding mean?memberDarekKawczynski31 Jul '06 - 4:34 
In Your code is line:
 
char[] padding={'\0','\0'}; // Two bytes for backup bits
 
I noticed that those two bytes are not present in all pdbs. Is it possible? Why in some pdbs they are not present?
 

 
Dario
AnswerRe: what does padding mean?memberMRSumra2 Aug '06 - 4:18 
Hi Dario!
These two bytes are appended after list Area before Data Area,,
can you send those pdb's at my e-mail address(rsumra@hotmail.com),
so that i can check this,,
 

 
Muhammad Rizwan Sumra

GeneralPDB generator in C#memberTime Lord18 Jul '06 - 12:05 
Great work Big Grin | :-D , saved me a headache.
 
Thanks
 
Cool | :cool: Timelord Cool | :cool:
GeneralGreat codememberrobertoy17 Jul '06 - 13:03 
This code is great. Since I am developing on VB .net right now, I translated it to VB.NET, will post code soon.
GeneralRe: Great codememberMRSumra20 Jul '06 - 4:16 
use following site to convert this code into VB.Net
http://www.developerfusion.co.uk/utilities/convertcsharptovb.aspx
 
Muhammad Rizwan Sumra
QuestionHow to install sqlce for PPC device?memberluongthang17 Jun '06 - 22:24 
I have a PPC device, i have a sqlce app. I want to run my app on PPC, how to install sqlce server for ppc?
 
hi
GeneralNot working for mememberhaucks12 Apr '06 - 6:52 
Just so you know.
 
I am running .NET 2005 and the code does not function properly for me.
 
I will look into it but it appears that the code where the loop to write the output is never completes.
 
I have 1238 rows in a csv file but it never completes the run.
 
Also I may have some data that is not compatible with your generic writer.
 

GeneralRe: Not working for mememberMRSumra15 Apr '06 - 1:06 
Ok, i don't check this in VS2005, but wait couple of days
i am developing another version that is to be finalized, this
will compatible for every possible datatype.

 
Muhammad Rizwan Sumra
GeneralRe: Not working for mememberhaucks17 Apr '06 - 10:33 
Sounds great, thanks.

GeneralRe: Not working for mememberpalmuser12318 Aug '08 - 1:47 
Hi
 
Please let me know when you will be updating this article with the latest version of PDB generator that supports all datatypes instead of only strings...
 
Thanks
GeneralRead PDBsmemberenshosinho16 Mar '06 - 3:24 
Muhammad,
 
GeneratePDB is very good, do you have any code in C# to read this PDB file?
 
Thank you very much
 
enshosinho

GeneralRe: Read PDBsmemberMRSumra15 Apr '06 - 1:09 
I have code but need to finalize, after that this
will be online.
 
Muhammad Rizwan Sumra
GeneralRead PDBs in both Pocket and Palmmemberpablojag19 Jan '06 - 2:38 
First of all let me say good work. Then do you think it´s posible to create a PDB file in order that both Palm and Pocket PC devices can read it.
 
Thank you and keep this way
 
Take care of your ideas, they can come real
GeneralRe: Read PDBs in both Pocket and PalmmemberMRSumra20 Jan '06 - 18:05 
Ofcourse we can, i m currently working on this, hopefully in next week this article will be in this forum.
 
Rizwan Sumra
GeneralRe: Read PDBs in both Pocket and PalmmemberDaveCline27 Jan '06 - 8:15 
Rizwan,
What a coincidence, I was looking for just this topic about a month ago. You know of course why your efforts will be well rewarded? Well we have the Treo650 and now the Treo700w whose data is incompatible with each other. Having a common PDB base for data transfer will be a godsend to us developers who have to support both platforms now.
 
When you get your PDB reader working alongside of your PDB writer - do let me know. I'm willing to pay you for your efforts.
 
Regards,
Dave Cline
 

GeneralRe: Read PDBs in both Pocket and PalmmemberMRSumra1 Feb '06 - 17:45 
Dave,
okz, i will consider Treo700w data format,
 
Muhammad Rizwan Sumra
GeneralRe: Read PDBs in both Pocket and PalmmemberDaveCline2 Feb '06 - 5:57 
Muhammad,
I've got a java version of what you've written - again only the writer part.
 
Part of it looks something like this:
 
public PalmDBRecord(byte category, boolean dirty, boolean secret)
{
this.category = category;
this.dirty = dirty;
this.secret = secret;
data = ByteBuffer.allocate(65220);
data.order(ByteOrder.BIG_ENDIAN);
}

public PalmDBRecord()
{
this((byte)0, false, false);
}

public void addBoolean(boolean b)
{
if (b) data.put((byte)0xff);
else data.put((byte)0);
}

public void addInteger(short k)
{
data.putShort(k);
}
 
The reason I mention this is that it looks like in order to insert specific types of data into a PDB record one would need to write the data type bytewise and I don't see this in your PDBWriter code. But perhaps I miss something.
 
Let me know if you'd like assistance in this regard.
Dave Cline
GeneralRe: Read PDBs in both Pocket and PalmmemberMRSumra2 Feb '06 - 18:20 
Hi Dave,
my application only store string types variables, but we can store any data type according to our desire, basically i m saving string byte by byte , in this regard we can save any datatype at any sequence (little endian or big endian).
 
Muhammad Rizwan Sumra
GeneralRe: Read PDBs in both Pocket and PalmmemberDaveCline3 Feb '06 - 9:31 
Muhammad,
Maybe we can take this offline to corroborate and return later?
 
Dave Cline
davecline SPLAT gmail.com
GeneralRe: Read PDBs in both Pocket and PalmmemberAlexander Blood6 Sep '06 - 8:10 
When will you post the Reading a PDB code?
QuestionHow about reading pdb's?memberjavacas19 Jan '06 - 1:57 

It will be nice if we can use your class in order to read (and then modify) un pdb.
 

Great work
AnswerRe: How about reading pdb's?memberMRSumra20 Jan '06 - 17:51 
yes we can. a little bit logic will be required to fetch each record. In pdb file format starting address is present but there is no information about record size to be read so we need to start + end-of-record address. Which we can get from (next-rec address - prev-rec address) will give record size.
 
Rizwan Sumra
QuestionGenerate PRCs?memberPinx18 Jan '06 - 1:54 
Great job!
Now all we need is a .NET program to generate PRCs for us Big Grin | :-D
AnswerRe: Generate PRCs?memberMRSumra18 Jan '06 - 17:58 
PRCs are resource based database that requires extensive work and it's little bit difficult to put programming language in PRCs. But that would be considered in future.
 
Rizwan Sumra
GeneralThis is the WORK I m lookin for.....memberASPNEt Lover17 Jan '06 - 23:45 
Well Done!
 
Muhammad Naseer
JokeGreat JobmemberAwaisAhmedKhan17 Jan '06 - 22:34 
you did really a good job!
 
thanks Smile | :)
 
awais khan

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 10 Jan 2006
Article Copyright 2006 by MRSumra
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid