LonTonG

Scio Cui Credidi
See also: Other Geeks@INDC
Evolusi Teknologi

nerd46422fm3

Kemarin ada diskusi asyik soal 32bit vs 64bit. Win98, Windows Server 2008, Crypto lib, bla bla bla..
Evolusi teknologi, mantap!
Jadi inget juga sama ol' friend sayings (hehehe.. peace bro)

Nah, supaya tetap diingat orang, di tengah hiruk pikuknya teknologi baru, saya share ini (MASM based).. and remember: Win32 journey is surely full of fun! :)

.386
.model flat,stdcall
option casemap:none
include c:\masm32\include\windows.inc
include c:\masm32\include\user32.inc
includelib c:\masm32\lib\user32.lib
include c:\masm32\include\kernel32.inc
includelib c:\masm32\lib\kernel32.lib

WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

.DATA
ClassName db "MyFirstWinClass",0
AppName db "Hello Win32ASM",0

.DATA?
hInstance HINSTANCE ?
CommandLine LPSTR ?
.CODE
start:
invoke GetModuleHandle, NULL

mov hInstance,eax
invoke GetCommandLine 

mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine,\ SW_SHOWDEFAULT
invoke ExitProcess, eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
    LOCAL wc:WNDCLASSEX
    LOCAL msg:MSG
    LOCAL hwnd:HWND

    mov   wc.cbSize,SIZEOF WNDCLASSEX
    mov   wc.style, CS_HREDRAW or CS_VREDRAW
    mov   wc.lpfnWndProc, OFFSET WndProc
    mov   wc.cbClsExtra,NULL
    mov   wc.cbWndExtra,NULL
    push  hInstance
    pop   wc.hInstance
    mov   wc.hbrBackground,COLOR_WINDOW+1
    mov   wc.lpszMenuName,NULL
    mov   wc.lpszClassName,OFFSET ClassName
    invoke LoadIcon,NULL,IDI_APPLICATION
    mov   wc.hIcon,NULL
    mov   wc.hIconSm,NULL
    invoke LoadCursor,NULL,IDC_ARROW
    mov   wc.hCursor,eax
    invoke RegisterClassEx, addr wc
    invoke CreateWindowEx,NULL,\
                ADDR ClassName,\
                ADDR AppName,\
                WS_OVERLAPPEDWINDOW,\
                CW_USEDEFAULT,\
                CW_USEDEFAULT,\
                CW_USEDEFAULT,\
                CW_USEDEFAULT,\
                NULL,\
                NULL,\
                hInst,\
                NULL
    mov   hwnd,eax
    invoke ShowWindow, hwnd,CmdShow
    invoke UpdateWindow, hwnd

    .WHILE TRUE
                invoke GetMessage, ADDR msg,NULL,0,0
                .BREAK .IF (!eax)
                invoke TranslateMessage, ADDR msg
                invoke DispatchMessage, ADDR msg
   .ENDW
    mov     eax,msg.wParam
    ret
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
    LOCAL hdc:HDC
    LOCAL ps:PAINTSTRUCT
    LOCAL rect:RECT
    .IF uMsg==WM_DESTROY
        invoke PostQuitMessage,NULL
        ret
    .ELSEIF uMsg==WM_PAINT
        invoke BeginPaint, hWnd, ADDR ps
        mov hdc, eax
        invoke GetClientRect, hWnd, ADDR rect
        invoke DrawText, hdc, ADDR AppName, -1,ADDR \         rect, DT_SINGLELINE + DT_CENTER + DT_VCENTER
        invoke EndPaint, hWnd, ADDR ps
        ret
    .ELSE
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam
        ret
    .ENDIF
    xor eax,eax
    ret
WndProc endp

end start

 

Udah ah ngaconya, mau masak indomie dulu :)

N.B
1. Iczelion Win32ASM tutorial: http://win32assembly.online.fr (simply the best!)
2. Foto (itu bukan foto saya), saya ambil dari sini. (Geek is a nerd who makes money)

Share this post: | | | |
Posted: Jul 23 2009, 09:01 AM by LonTonG | with 2 comment(s)
Filed under:
Our Baby Is Finally Copyrighted

Setelah sekian lama menunggu (pengajuan Oktober 2007), tanpa kepastian..
Akhirnya beberapa hari yang lalu software yang kami buat sudah selesai didaftarkan dan terproteksi hingga 50 tahun ke depan.

Apa artinya secarik kertas ini buat kami?
Ini kami ibaratkan seperti seorang ibu yang baru melahirkan bayi. Sampai bayi tersebut didaftarkan, status bayi tersebut adalah tidak jelas (bisa juga dianggap di luar nikah). Lebih jauh artinya status hukumnya juga tidak jelas!

Nah, kondisi ini kurang lebih sama seperti software yang kita hasilkan.
Dengan adanya secarik kertas ini berarti secara hukum jelas siapa "bapaknya anak - anak" :)

 

HAKI 

 

Ke depan, kami siap untuk mengajukan lagi 2 - 3 bayi lagi, buah cinta kami :)
Siap - siap saja kelarnya tahun 2011, yeah baby!

Share this post: | | | |
Posted: Jun 26 2009, 08:06 PM by LonTonG | with 2 comment(s)
Filed under:
Write Your Own Cross-platform Application With IUP & GTK+

Lately I have been working on cross-platform application. This application should be running on at least Windows, Linux, *BSD, and Mac.

I have to pick up the right tool (for UI stuff) for me. First I tried IUP, I gotta admit I like IUP.
IUP is so simple, simple like this:

void init_dialog (void)
{
  Ihandle *mnu, *_hbox_1, *_cnv_1, *_vbox_1, *dlg, *img,
    *_frm_1;

  img = IupImage(32,32, img_bits1);
  IupSetHandle ("img1", img);
  IupSetAttribute (img, "0", "0 0 0");
  IupSetAttribute (img, "1", "BGCOLOR");
  IupSetAttribute (img, "2", "255 0 0");

    _frm_1 = IupFrame(
    IupVbox(
      IupButton("Button Text", "myaction"),
      IupSetAttributes(IupButton("", "myaction"), "IMAGE=img1"),
      IupSetAttributes(IupButton("", "myaction"), "IMAGE=img1,IMPRESS=img2"),
      NULL));
  IupSetAttribute(_frm_1,"TITLE","IupButton");

  ...

}

int main(int argc, char **argv)
{
IupOpen(&argc, &argv);
init_dialog();
IupShow(IupGetHandle("dlg"));
IupMainLoop();
IupClose();
return EXIT_SUCCESS;
}
 

These lines of code are self-explanatory.
IupOpen initializes the toolkit, init_dialog is the function where we create and position our own dialog that contains controls/widgets, IupShow display the dialog, IupMainLoop is the message loop where it receives, translates and dispatches message, just like

while(GetMessage(&msg, NULL, 0, 0)) {

    TranslateMessage(&msg);
    DispatchMessage(&msg);

}

And finally IupClose, destroying IUP and release the memory occupied. I have attached IUP sample code that can be used to be observed.

image

Unfortunately, for some reasons I have to leave IUP, and move on to GTK+.

Back in 2004, I bought a book about GTK+ programming.

image

Nice book eh? :)

And now, for the GTK+ programming. Observe this:

GtkWidget *
do_dialog (GtkWidget *do_widget)
{
  GtkWidget *frame;
  GtkWidget *vbox;
  GtkWidget *vbox2;
  GtkWidget *hbox;
  GtkWidget *button;
  GtkWidget *table;
  GtkWidget *label;

  if (!window)
    {
      window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
      gtk_window_set_screen (GTK_WINDOW (window),
                 gtk_widget_get_screen (do_widget));
      gtk_window_set_title (GTK_WINDOW (window), "Dialogs");

      g_signal_connect (window, "destroy", G_CALLBACK (gtk_widget_destroyed), &window);
      gtk_container_set_border_width (GTK_CONTAINER (window), 8);

      frame = gtk_frame_new ("Dialogs");
      gtk_container_add (GTK_CONTAINER (window), frame);

      vbox = gtk_vbox_new (FALSE, 8);
      gtk_container_set_border_width (GTK_CONTAINER (vbox), 8);
      gtk_container_add (GTK_CONTAINER (frame), vbox);

...

}

int main(int argc, char *argv[])
{
    gtk_init (&argc, &argv);
    window = do_dialog(window);
    gtk_main ();

    return 0;
}

image

What I really like about GTK+ is her ability to build an interface by loading XML file. If you want to know more about this, please go to this site.

To load this demo.xml file:

<interface>
<object class="GtkDialog" id="dialog1">
<child internal-child="vbox">
<object class="GtkVBox" id="vbox1">
<property name="border-width">10</property>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="hbuttonbox1">
<property name="border-width">20</property>
<child>
<object class="GtkButton" id="ok_button">
<property name="label">gtk-ok</property>
<property name="use-stock">TRUE</property>
<signal name="clicked" handler="ok_button_clicked"/>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>

We need this:

builder = gtk_builder_new ();
filename = demo_find_file ("demo.xml", NULL);
gtk_builder_add_from_file (builder, filename, &err);

gtk_builder_connect_signals (builder, NULL);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window1"));

The great thing about this is that we can totally separate UI design from the code side. One can create UI design by using Glade, or manually typing an XML.
Oh by the way, because GtkBuilder arrives after libglade (and now almost everyone migrates from libglade to GtkBuilder), we must use a tool to convert file generated by Glade to fully conform GtkBuilder's file specification, we can use gtk-builder-convert (this is a phyton script)

gtk-builder-convert [OPTION] [INPUT] [OUTPUT]

 

OK, happy weekend!


Bakwan Duta Malang, here I come! :)

Share this post: | | | |
Posted: Apr 25 2009, 03:42 PM by LonTonG | with 6 comment(s)
Filed under: , ,
Control Your Network With LSP & WFP

Beberapa bulan (8 bulan?) yang lalu saya sempat ngobrol yang cukup serius tentang network sniffer atau lebih tepatnya network packet injection karena akan ada injeksi sesuatu ke dalam packet data yang akan masuk. Waktu itu saya diberi masukan untuk explore lebih dalam tentang WinPcap. WinPcap mengingatkan saya tentang pcap, tcpdump, nmap (tool ini bikin ketagihan :)
Setelah buka ini buka itu, kok sepertinya WinPcap bukan alat yang tepat untuk kebutuhan injeksi packet data. In fact, link ini tambah memperkuat keyakinan saya bahwa pcap tidak mampu untuk menginjeksi packet data, karena pcap hanya mampu untuk meng-capture data (sesuai dengan namanya :p).

OK, perjalanan berlanjut hingga ketemu dengan yang namanya LSP (dan nantinya WFP, ya WFP bukan WPF). Dan dipost saya kali ini saya akan coba share apa yang telah saya dapat pelajari dan fokus pada LSP. Oh ya, sebelumnya saya harus mengingatkan untuk berhati - hati dalam mencoba - coba LSP, kesalahan sedikit bisa berakibat fatal (network yang jadi kacau balau hingga kasus yang ekstrim yaitu re-installing windows). Ini tidak berlebihan karena segala sesuatu yang agak - agak low level berbahaya.

LSP atau Layered Service Provider adalah suatu fitur dari Winsock 2 Service Provider Interface (SPI) yang memungkinkan programmer untuk membangun suatu komponen/aplikasi yang dapat me-monitor atau bahkan me-modifikasi packet data, inbound maupun outbound. LSP yang merupakan suatu windows dll, yang apabila sudah diload akan me-"layer" kan base provider (atau bisa juga me-"layer" kan layered provider lainnya), seperti illustrasi di bawah:

LayeredProvider_Architecture

Jadi apabila biasanya alurnya dari ws2_32.dll langsung ke base provider (TCP/IP dan UDP/IP atau RSVP provider), sekarang akan ada layered provider di antara base provider dan ws2_32.dll. Gambar di bawah mungkin akan lebih memperjelas.

SPI_Architecture

Nah, seperti disinggung di atas, karena LSP tidak lain dan tidak bukan adalah windows dll, maka harus ada 1 function entry yang akan di-export, yaitu WSPStartup. Function entry inilah yang akan meng-inisiasi SPI. Di sini pulalah akan ada pemetaan fungsi - fungsi standard seperti WSASocket, WSAAccept, WSAConnect, Bind, WSARecv, shutdown ke "versi" SPI seperti: WSPAccept, WSPSocket, WSPConnect, WSPBind, WSPRecv, WSPShutdown (± ada 30 SPI function) melalui function dispatch table.
Oh ya, coba perhatikan prefix dari function tersebut.


Jadi apabila aplikasi yang akan kita buat memanggil salah satu winsock function, contoh: WSAConnect, WS2_32.DLL akan memanggil fungsi yang terkait, yaitu: WSPConnect.
Berikut contoh pemetaan SPI function di WSPStartup:

gProcTable.lpWSPAccept = WSPAccept;
gProcTable.lpWSPAddressToString = WSPAddressToString;
gProcTable.lpWSPAsyncSelect = WSPAsyncSelect;
gProcTable.lpWSPBind = WSPBind;
gProcTable.lpWSPCancelBlockingCall = WSPCancelBlockingCall;
gProcTable.lpWSPCleanup = WSPCleanup;
gProcTable.lpWSPCloseSocket = WSPCloseSocket;
gProcTable.lpWSPConnect = WSPConnect;
gProcTable.lpWSPDuplicateSocket = WSPDuplicateSocket;
gProcTable.lpWSPEnumNetworkEvents = WSPEnumNetworkEvents;
gProcTable.lpWSPEventSelect = WSPEventSelect;
gProcTable.lpWSPGetOverlappedResult = WSPGetOverlappedResult;
gProcTable.lpWSPGetPeerName = WSPGetPeerName;
gProcTable.lpWSPGetSockOpt = WSPGetSockOpt;
gProcTable.lpWSPGetSockName = WSPGetSockName;
gProcTable.lpWSPGetQOSByName = WSPGetQOSByName;
gProcTable.lpWSPIoctl = WSPIoctl;
gProcTable.lpWSPJoinLeaf = WSPJoinLeaf;
gProcTable.lpWSPListen = WSPListen;
gProcTable.lpWSPRecv = WSPRecv;
gProcTable.lpWSPRecvDisconnect = WSPRecvDisconnect;
gProcTable.lpWSPRecvFrom = WSPRecvFrom;
gProcTable.lpWSPSelect = WSPSelect;
gProcTable.lpWSPSend = WSPSend;
gProcTable.lpWSPSendDisconnect = WSPSendDisconnect;
gProcTable.lpWSPSendTo = WSPSendTo;
gProcTable.lpWSPSetSockOpt = WSPSetSockOpt;
gProcTable.lpWSPShutdown = WSPShutdown;
gProcTable.lpWSPSocket = WSPSocket;
gProcTable.lpWSPStringToAddress = WSPStringToAddress;

Selanjutnya kurang lebih sama, yaitu implementasi fungsi terkait, contoh: WSPConnect

OK, cukup dulu sampai di sini. Untuk sementara kita akan lompat ke bagian instalasi LSP.
Memang benar bagian instalasi LSP bisa jadi sangat membingungkan karena begitu kompleks, dan di sini saya tidak akan membahas terlalu dalam.
Bagian yang pertama adalah kita harus meng-enumerasikan Winsock catalog.
Pada bagian ini akan digunakan struktur WSAPROTOCOL_INFOW, seperti berikut:

typedef struct _WSAPROTOCOLCHAIN {
    int ChainLen;
    DWORD ChainEntries[MAX_PROTOCOL_CHAIN];
} WSAPROTOCOLCHAIN, FAR * LPWSAPROTOCOLCHAIN;

ChainLen memberitahukan tipe dari provider, contoh 1 merupakan base provider (TCP/IP dan UDP/IP atau RSVP provider).
Setelah itu kita akan panggil fungsi WSCInstallProvider untuk meng-instalasikan provider.

int WSPAPI
WSCInstallProvider(
    IN LPGUID lpProviderId,
    IN const WCHAR FAR *lpszProviderDllPath,
    IN const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
    IN DWORD dwNumberOfEntries,
    OUT LPINT lpErrno
);

Setiap provider yang akan kita instalasikan memerlukan suatu GUID yang merupakan identitas unik dari provider tersebut. GUID ini bisa kita buat dengan memanggil fungsi UuidCreate atau dengan menggunakan program guidgen (pada Visual Studio 2008 terdapat pada: C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools)

guidgen

Terakhir, kita perlu memanggil fungsi WSCWriteProviderOrder

int WSPAPI WSCWriteProviderOrder( IN LPDWORD lpdwCatalogEntryId, IN DWORD dwNumberOfEntries );

Untuk mengatur ulang winsock catalog (ingat yang kita enumerasikan sebelumnya?), supaya LSP yang kita buat berada di atas provider yang kita "layer" kan (contoh: TCP/IP UDP/IP provider), kalau tidak diatur ulang catalog ini maka LSP tidak akan berjalan.

Perhatikan 2 gambar berikut

ServiceProviders_List

ServiceProviders_List_Reorder

Sedangkan untuk menghapus entry LSP, cukup dengan memanggil fungsi WSCDeinstallProvider dengan id dari provider yang ingin kita hapus.

int WSPAPI WSCDeinstallProvider(
        IN LPGUID lpProviderId,
        OUT LPINT lpErrno
);

Hanya harap berhati - hati saat menghapus entry LSP, kita harus pastikan reference dari LSP yang akan dihapus. Salah - salah windows tidak bisa boot (seperti sudah saya peringatkan di awal artikel ini)

Selain 2 fungsi di atas, bisa juga kita modifikasi LSP yang ada dengan:

int WSPAPI WSCUpdateProvider(
        IN LPGUID lpProviderId,
        IN const WCHAR FAR *lpszProviderDllPath,
        IN const LPWSAPROTOCOL_INFOW lpProtocolInfoList,
        IN DWORD dwNumberOfEntries,
        OUT LPINT lpErrno
);

Parameter pada fungsi ini sama persis dengan yang ada di fungsi WSCInstallProvider, hanya bedanya WSCUpdateProvider mengupdate LSP yang ada bukannya membuat baru.

Tidak lupa kita panggil fungsi WSPCloseSocket & WSPCleanup setelah selesai. (DLL_PROCESS_ DETACH)

OK, kita berhenti lagi sampai di sini. Saya rasa akan lebih baik kalau langsung kita bahas implementasi nya langsung.
Pada contoh sederhana berikut saya akan membuat blokir terhadap semua website kecuali yang ber-IP 202.155.61.90 (geeks.netindonesia.net)

int WSPAPI WSPConnect (
    SOCKET                s,
    const struct sockaddr FAR * name,
    int                   namelen,
    LPWSABUF              lpCallerData,
    LPWSABUF              lpCalleeData,
    LPQOS                 lpSQOS,
    LPQOS                 lpGQOS,
    LPINT                 lpErrno
)
{
    SOCK_INFO *SocketContext;
    INT        ret;

    const char *pszSourceAddress = inet_ntoa(((struct sockaddr_in *)name)->sin_addr);
    const char *pszMatchAddress = "202.155.61.90";

    if (strcmp(pszSourceAddress,pszMatchAddress) != 0)
        return SOCKET_ERROR;

...

}

Simple, berikan saja SOCKET_ERROR sebagai nilai kembalian pada fungsi WSPConnect apabila source address dan match address tidak cocok. (yaitu != 0)

Atau contoh berikut untuk memonitor packet data yang masuk (sebagai contoh saat saya browsing website geeks.

int WSPAPI WSPRecv(
    SOCKET          s,
    LPWSABUF        lpBuffers,
    DWORD           dwBufferCount,
    LPDWORD         lpNumberOfBytesRecvd,
    LPDWORD         lpFlags,
    LPWSAOVERLAPPED lpOverlapped,
    LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
    LPWSATHREADID   lpThreadId,
    LPINT           lpErrno)
{
    LPWSAOVERLAPPEDPLUS ProviderOverlapped;
    SOCK_INFO          *SocketContext;
    int                 ret;

    OutputDebugString(lpBuffers->buf);

...

}

Di sini saya gunakan fungsi OutputDebugString untuk meng-outputkan packet data yang masuk. Output ini bisa kita lihat dengan (salah satunya) program dbgview (saya sangat suka dengan tool ini). Satu hal yang sering diwanti - wanti adalah jangan menggunakan MessageBox untuk melihat/mengecheck packet data, ini bisa berakibat fatal. (beberapa service dapat me-load dll LSP bahkan sebelum UI subsystem selesai diinisialisasikan pada saat booting windows) 

dbgview

Nah sekarang kita bisa melakukan network packet injection :)


Saya sertakan demo dari contoh di atas berikut UI nya supaya tidak repot untuk melakukan instalasi LSP.
Untuk menjalankan demo, cukup letakan file MyLSP.dll ke c:\windows\system32, dan jalankan file MyLSPGUI.exe. Klik OK untuk mengaktifkan LSP dan Cancel untuk menonaktifkan LSP.
Untuk melihat efek dari demo ini, ada baiknya web browser ditutup terlebih dahulu sebelum menjalankan demo.
btw, resiko ditanggung sendiri :D

Semoga pada artikel berikutnya saya bisa sharing lebih dalam tentang LSP (IFS handles, socket IO, dll) + WFP (dan mengapa WFP lebih baik dari LSP).

referensi:
http://www.microsoft.com/msj/0599/LayeredService/LayeredService.aspx
http://www.microsoft.com/whdc/device/network/wfp.mspx
http://blogs.msdn.com/wndp/default.aspx

 

N.B:
mohon dimaklumi apabila penggunaan kata - katanya mungkin rancu dan campur aduk, sekarang jam 2:56 AM.. mata sudah mulai kreyep - kreyep dan pikiran saya masih terbagi dengan rusaknya power window mobil saya sore ini :(

Share this post: | | | |
Posted: Mar 27 2009, 02:59 AM by LonTonG | with 2 comment(s)
Filed under:
IE8 My First Impression

Today, right after i read Wely's post about IE8, i downloaded IE8 and installed it. Everything went OK.

So i started to browse few sites. Kaskus, Yahoo! Mail, Detik, and Raymond's blog.
And sadly i got this:

first_impression2

I tried to reproduce the error, and i'm almost sure that the problem is caused by detik's site. (yeah, you know)


0xC0000005 at 0x8bcce963

I might want to dig up more about this. Gee, this is not a good first impression.

Share this post: | | | |
Posted: Mar 20 2009, 01:01 PM by LonTonG | with 2 comment(s)
Filed under:
Win32 Tiny Tip For Communicating Two Processes - Lanjutan (Free SMS Live Show)

Karena tidak ada kerjaan akhir pekan ini (selain nonton Chris "The Dragon" John :)), saya coba buat live show dari artikel saya yang pertama tentang meng-komunikasikan 2 proses dengan cara yang sangat sederhana.

Di sini saya coba buatkan suatu web interface (compiled C yang saya jadikan CGI). Setiap request dari web langsung di WM_COPYDATA kan ke aplikasi sesungguhnya (SMS Gateway).

OK, langsung saja dicobain:
http://lontong.mooo.com:8080/sms.html

N.B:
1. Mohon maaf kalau kecepatan akses ke www servernya lelet, karena ini hanya home cable (Fastnet 384)
2. Free SMS hanya untuk mengirim saja (karena memang hanya untuk contoh saja, bukan untuk SMS gateway sesungguhnya), dan saya batasi hanya 100 SMS / hari. Harap maklum :)
3. Tolong jangan vandal. Proteksi di live show ini minim sekali (no captcha, way too simple URL encoding, etc)
4. Salut untuk mas Chris John :)

Share this post: | | | |
Posted: Mar 01 2009, 01:35 PM by LonTonG | with 2 comment(s)
Filed under: ,
Win32 Tiny Tip For Communicating Two Processes

Ada kalanya kita perlu mengkomunikasikan 2 (atau lebih) program lokal yang sedang berjalan (proses) untuk keperluan tertentu, contoh monitoring agent, packer sniffer, process viewer, dll

Banyak cara untuk ini:

  • socket
  • pipes (anonymous / named)
  • shared memory
  • temporary file

Sering kali kita merasa untuk mengkomunikasikan beberapa proses untuk sesuatu yang sederhana begitu rumit. Untuk socket, kita harus membuat "parent to babysit the child" (istilah Raymond Chen). Kemudian untuk pipes, kita harus CreatePipe, ReadFile, WriteFile, sambil berharap kita tidak lupa untuk CloseHandle, dst..

Masak untuk mengirim data yang sederhana begitu saja `njlimet? Apa tidak ada cara yang sederhana?
Well, sebenarnya ada.. gunakan saja WM_COPYDATA!

Secara teknis kurang lebih seperti ini:

Pada sisi pengirim data (sender), sender melewatkan struktur COPYDATASTRUCT yang berisikan data yang akan dikirimkan sebagai LPARAM dari WM_COPYDATA.
Contoh:

typedef struct SMSDATA {
    char szMsisdn[15];
    char szMessage[161];
};
...

void OnCopyData(LPARAM lParam)
{

    COPYDATASTRUCT MyCDS;
    HWND hDestination;

    struct SMSDATA SMSData;

    /* clear the structure first */
    memset(&SMSData, 0, sizeof(struct SMSDATA));

    GetDlgItemText(hParent, IDC_EDIT_NOMOR, SMSData.szMsisdn, 15);
    GetDlgItemText(hParent, IDC_EDIT_ISI, SMSData.szMessage, 161);

    MyCDS.dwData = 0;
    MyCDS.cbData = sizeof(struct SMSDATA);
    MyCDS.lpData = &SMSData;

    hDestination = FindWindow(NULL, "SMSbox :: The SMS Manager");

    if( hDestination != NULL ) {
        SendMessage( hDestination, WM_COPYDATA, (WPARAM)(HWND) hParent, (
            LPARAM)(COPYDATASTRUCT*) &MyCDS );
        }

...

}

Lalu pada sisi receiver (penerima), langsung ambil & proses data.
Contoh:

case WM_COPYDATA:
    {
        PCOPYDATASTRUCT pMyCDS;
        struct SMSDATA SMSData;

        pMyCDS = (PCOPYDATASTRUCT) lParam;

        /* Clear & fill the structure */
        memset(&SMSData, 0, sizeof(struct SMSDATA));
        memcpy(&SMSData, (const void *)pMyCDS->lpData, sizeof(struct SMSDATA));

...

Simple & straightforward right?

Beberapa hal berikut layak mendapat perhatian saat menggunakan WM_COPYDATA:

1. Kita harus yakin receiver (penerima) benar - benar pihak yang dituju, dan bukan hanya sekedar sama namanya (via FindWindow()), atau kalaupun benar yang dituju.. sangat baik untuk dicheck kembali instancenya (karena sering kita menjalankan program yang sama, bersamaan dalam waktu yang sama (???), contoh: web browser, dll
2. Berkaitan dengan poin #1, penggunaan WM_COPYDATA yang sembrono (broadcasting WM_COPYDATA secara membabi buta) bisa bikin polusi :)
3. Hati - hati terhadap penyalahgunaan WM_COPYDATA, contoh mengirimkan WM_COPYDATA bogus untuk tujuan yang negatif, contoh: membuat program crash, dll
4. Data yang hendak dilewatkan tidak boleh berupa pointer (this hit me once), alasannya cukup jelas saya rasa.

Share this post: | | | |
Posted: Feb 24 2009, 12:41 AM by LonTonG | with 4 comment(s)
Filed under: ,
Win32 Tiny Tip On Using Common Controls

It's important to know that you need to call InitCommonControlsEx function with INITCOMMONCONTROLSEX structure members: dwSize (size in bytes) & dwICC. (which common controls class to load) if you want to use common controls.

Suppose we want to use these 2 common controls (DTP, and Listview)

Common Controls

You can add these lines of code in your WinMain function or in WM_INITDIALOG section if you're working on a dialog based app or in your WM_CREATE section if you're working on a window based app:

INITCOMMONCONTROLSEX icex;

icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC  = ICC_DATE_CLASSES | ICC_LISTVIEW_CLASSES;
InitCommonControlsEx(&icex);

dwICC member could be combinations of these:

ICC_ANIMATE_CLASS
ICC_BAR_CLASSES
ICC_COOL_CLASSES
ICC_DATE_CLASSES
ICC_HOTKEY_CLASS
ICC_INTERNET_CLASSES
ICC_LINK_CLASS
ICC_LISTVIEW_CLASSES
ICC_NATIVEFNTCTL_CLASS
ICC_PAGESCROLLER_CLASS
ICC_PROGRESS_CLASS
ICC_STANDARD_CLASSES
ICC_TAB_CLASSES
ICC_TREEVIEW_CLASSES
ICC_UPDOWN_CLASS
ICC_USEREX_CLASSES
ICC_WIN95_CLASSES

It's also important to note that the effect of each call to InitCommonControlsEx is cumulative, that is if you call InitCommonControlsEx with ICC_DATE_CLASSES flag and then you call InitCommonControlsEx again with ICC_TREEVIEW_CLASSES, both common controls class are registered.

Failure to do this, You might end up something like wasting your precious 30 mins with head scratching. :)

Share this post: | | | |
Posted: Jan 18 2009, 02:18 PM by LonTonG | with no comments
Filed under:
ESE, Microsoft's Embeddable Database

Mungkin ada benarnya juga kata pengantar di blog Windows SDK yang membahas tentang ESE, bahwa sedikit orang tahu / minimal pernah dengar ESE.

Apa itu ESE? Rokok produksi Korea yang cukup terkenal di Indonesia atau European Society of Endocrinology ?
Dua - dua nya bukan :)

Penjelasan yang (menurut saya) paling singkat & tepat untuk ESE atau Extensible Storage Engine adalah:

Windows' embeddable & transactional database engine

Sedangkan penjelasan yang detail ada di wikipedia.

Embeddable? Ya, ESE dapat kita sisipkan ke dalam aplikasi yang kita buat, tersembunyi. ESE mirip dengan produk Microsoft lainnya, yaitu SQL Server CE dalam hal runs in-process with application, namun yang menjadi perbedaan mencolok adalah dukungan terhadap SQL queries. ESE tidak mendukung SQL queries.

Tidak mendukung SQL queries? Jadi?
Tentunya dengan menentukan terlebih dahulu queries yang akan kita gunakan. Lebih lanjut akan dibahas di bawah.

Kemudian Transactional? Ya, ACID with savepoints, lazy commits and robust crash recovery.

Contoh penggunaan ESE adalah Active Directory, Windows Desktop Search, Windows Mail, Microsoft Exchange, Microsoft Updates, Local Security Policy, dll.
Lalu apa yang kita bisa manfaatkan dari ESE? Kalau aplikasi yang akan kita bangun mempunyai kebutuhan untuk storing data dengan queries yang simple dan telah (dapat) kita prediksikan sebelumnya (detail dapat dilihat pada posting saya sebelumnya tentang Berkeley DB, yang semoga saja tidak lenyap ditelan bumi sewaktu ada masalah dengan situs geeks), maka tentu saja ESE akan jadi sangat berguna.

Lalu apa saja keunggulan ESE? Berikut daftarnya, yang saya ambil kembali dari blog Laurion Burchall (Software Design Engineer, ESENT Team):

    • ACID transactions with savepoints, lazy commits and robust crash recovery.
    • Snapshot isolation.
    • Record-level locking — multi-versioning provides non-blocking reads.
    • Highly concurrent database access.
    • Flexible meta-data (tens of thousands of columns, tables and indexes are possible).
    • Indexing support for integer, floating point, ASCII, Unicode and binary columns.
    • Sophisticated index types including conditional, tuple and multi-valued.
    • Individual columns can be up to 2GB in size. A database can be up to 16TB in size.
    • Can be configured for high performance or low resource usage.
    • No administration required (even the database cache size can adjust itself automatically).
    • No download. Your application uses the esent.dll which comes with the operating system.

OK, cukup dengan teori.

Alur tipikal dari ESE adalah sebagai berikut:

  JetCreateInstance()
     JetInit()
         JetBeginSession()
             JetAttachDatabase()
                 JetOpenDatabase()
                     JetOpenTable()
                     JetCloseTable()
                 JetCloseDatabase()
             JetDetachDatabase()
         JetEndSession()
     JetTerm()

Berikut contohnya:

#include <windows.h>
#include <esent.h>

#define Call(func) { \
       err = (func); \
       if(err < JET_errSuccess) { \
       goto HandleError; \
       } \
} \

BOOL CreateESE(HWND hwnd)
{

    JET_ERR err;
    JET_INSTANCE instance;
    JET_SESID sesid;
    JET_DBID dbid;
    JET_TABLEID tableid;

    JET_COLUMNID columnid;
    JET_COLUMNDEF columndef = {0};

    char szBuffer[32] = "";
    char *pszData = "Holla Mundo";

    Call(JetCreateInstance(&instance, "instance"));
    Call(JetSetSystemParameter(&instance, JET_sesidNil, JET_paramCircularLog, 1, NULL));
    Call(JetInit(&instance));
    Call(JetBeginSession(instance, &sesid, 0, 0));

    /* Create database first if not exists */
    Call(JetCreateDatabase(sesid, "MyDatabase.db", 0, &dbid, JET_bitDbOverwriteExisting));

    Call(JetBeginTransaction(sesid));

    /* Create table too */
    Call(JetCreateTable(sesid, dbid, "MyTable", 0, 100, &tableid));

    columndef.cbStruct = sizeof(columndef);
    columndef.coltyp = JET_coltypLongText;

    /* We use no unicode */
    columndef.cp = 1252;
    Call(JetAddColumn(sesid, tableid, "MyColumn", &columndef, NULL, 0, &columnid));
    Call(JetCommitTransaction(sesid, JET_bitCommitLazyFlush));

    Call(JetBeginTransaction(sesid));
    Call(JetPrepareUpdate(sesid, tableid, JET_prepInsert));

    Call(JetGetTableColumnInfo(sesid, tableid, "MyColumn", &columndef, sizeof (JET_COLUMNDEF), JET_ColInfo));
    Call(JetSetColumn(sesid, tableid, columndef.columnid, pszData, strlen(pszData) + 1, 0, 0));
    Call(JetUpdate(sesid, tableid, NULL, 0, NULL));
    Call(JetCommitTransaction(sesid, 0));

    /* Start querying record */
  Call(JetMove(sesid, tableid, JET_MoveFirst, 0));

    do {
            Call(JetBeginTransaction(sesid));
            Call(JetRetrieveColumn(sesid, tableid, 0, szBuffer, sizeof(szBuffer), NULL, 0, NULL));
            Call(JetCommitTransaction(sesid, 0));
            SendMessage(GetDlgItem(hwnd, IDC_LIST_NAME), LB_ADDSTRING, 0, (LPARAM) szBuffer);
    }
    while(JET_errSuccess == JetMove(sesid, tableid, JET_MoveNext, 0));   

    JetCloseTable(sesid, tableid);
    JetEndSession(sesid, 0);
    JetTerm(instance);

    return TRUE;

}

Bagi saya, (seperti halnya Berkeley DB) ESE ini sangat menarik. Beberapa poin yang terutama saya sukai dari ESE ini adalah: mekanisme crash recovery, runtime yang ada di mana - mana (well, sebenarnya mulai dari Windows 2000) sehingga memudahkan deployment, dan tak lupa performanya.

Namun, seperti saya kutip di atas dari blog Windows SDK tentang ESE, sedikit orang tahu / minimal pernah dengar ESE. Ini sungguh disayangkan, karena banyak industri yang dapat memanfaatkan ESE, contoh: log & billing management (telco, banking, dll)

(mungkin) Hambatan terbesar bagi yang ingin mengenal ESE lebih dalam adalah minimnya informasi tentang ESE itu sendiri (dokumentasi, sample code, dll). Dan ini saya rasakan sendiri.
Bahkan setahu saya di MSDN yang membahas tentang ESE pun, minim sekali (tidak lebih dari 15 halaman?)
Semoga ke depan ESE bisa berkembang, dan jangan sampai seperti beberapa teknologi Microsoft lainnya yang kandas di tengah jalan. Semoga :)

 

P.S
Saya sertakan contoh aplikasi sederhana yang memanfaatkan ESE, yang saya buat dengan menggunakan Visual Studio 2008. UI juga dibuat sesederhana mungkin (Win32 + C)

EsentFirstAttempt.zip

 

Share this post: | | | |
Posted: Jan 08 2009, 03:24 AM by LonTonG | with 3 comment(s) |
Filed under: ,
Permenungan Di Awal Tahun

Lagi hujan nih di sukabumi, jadi kepikiran juga untuk evaluasi 2008. What have I done. Di tahun 2008 ini ada beberapa kejadian besar dalam hidup saya (eg. getting married, serius ngegarap usaha microISV, dll)

Salah satu yang tidak ketinggalan penting menurut saya adalah perkenalan dengan komunitas geeks.netindonesia.net. Kalau tidak salah waktu itu saya dateng ke event berbau IT, yang namanya iMulai, di Blitz Megaplex. Di flyer, saya lihat ada beberapa link yang menarik, salah satunya geeks.netindonesia.net, ya udah mulai deh ikutan.. walau pertama cuma lirik - lirik. Jujur kesan pertama ikutan komunitas ini: bingung. Kok semua pada ngomongin .NET? Lha yang lain pada kemana? Ditambah saya sendiri datang dari dunia yang jadoel.. jadi serasa manusia purba :)

Ah tapi as time goes on, saya bertemu dengan orang - orang yang luar biasa (salah satunya Pak Risman), melalui percakapan demi percakapan, saya merasa sangat diterima, and i mean it.

Nah, sekarang 2008 sudah lewat 1 hari. Dalam beberapa perbincangan yang cukup intens dengan beberapa teman saya (sesama shareware author), saya merasa ada beberapa hal yang harus saya ubah. Salah satunya adalah software (esp. UI) usability.

Untuk beberapa tahun belakangan ini, seolah sudah menjadi ciri khas sendiri buat saya UI berikut:

tabernus2 

Tabernus

image

Win32MyAdmin

image

Libellus

image

SMStron

Saya ingat awal tahun 2005, saat saya masih bekerja di salah satu perusahaan di Kelapa Gading, salah seorang rekan saya (he called himself as the father of all magabutterz :)) bahkan pernah `nyeletuk, dia bilang: "ah.. si mbah (yes, that's me) mah dah ketauan model (desain) tampilan software nya". Walaupun ini cuma sekedar omongan kosong alias intermezzo, namun saya merasa ada benarnya juga. Tanpa sadar saya sudah memprogram otak saya, sehingga saat mulai pada stage - stage awal desain prototipe software yang akan saya buat, sudah terkonsep UI nya. Dan (again), tanpa sadar ini terbawa terus hingga sekarang. Benar - benar menakjubkan bagaimana alam bawah sadar kita bekerja.

Sekarang kembali lagi ke UI's yackety yak. WPF benar - benar menarik perhatian saya. Coba lihat Ahmad Masykur Organization Chart Viewer. Manis!
Kembali saya jadi ingat, saat saya mengerjakan aplikasi HRD untuk Spers TNI (2004 or something). Kurang lebih konsepnya sama dengan apa yang mas Ahmad Masykur buat, hanya spesifik untuk lingkungan militer. Saya ingat pengerjaannya cukup challenging. Banyak sekali kontrol yang harus dibuat sendiri (melalui owner & custom draw) untuk memfasilitasi keinginan pengguna (contoh: penggunaan warna pada kontrol untuk me-marking status personel seseorang (normal, soon will be retired, need to be retired now, etc)). Bandingkan dengan apa yang WPF lakukan. (walaupun sampai saat ini saya alergi dengan enkapsulasi yang berlebihan).

Saya tidak tahu apa jadinya apabila WPF sudah ada dari tahun 2003 :)

OK, mungkin sudah saatnya saya digging up sesuatu yang baru, terlebih untuk UI. (ada teman saya yang rekomendasiin Adobe AIR), but wait.. tentunya ini (saran, pemikiran, dll) tidak akan serta merta saya telan begitu saja. Ada banyak hal juga yang dapat menjadi konstrain buat saya, yaitu: efisiensi. Saya (juga) alergi kepada teknologi yang cumbersome (terutama buat pengguna).

Oh ya, saya berharap rencana - rencana saya lainnya di tahun 2009 ini bisa terlaksana, salah satunya yang sedang saya ngobrolin dengan Pak Risman.

Semoga.

Share this post: | | | |
Posted: Jan 01 2009, 05:38 PM by LonTonG | with 2 comment(s)
Filed under:
Illegal Move?

Saatnya santai sedikit :)
Ada yang bisa bantu saya dengan "problem" yang saya alami berikut?


Chess Titans under Vista Ultimate, sedikit lagi menang, tapi..
Berikut kronologinya:

 

move_1

OK, pion lawan (warna putih) maju 1 langkah mendekati raja saya (warna hitam)

 

move_2

Saya ganti merangsek ke depan.. pion (di samping raja) akan saya majukan 2 langkah ke depan

move_3

Wuss.. posisi pion manteng di depan.. Mantap!

move_4

Lho.. lho.. lho? kok pion musuh bisa makan pion saya yang berada tepat di sebelah kiri dia? Pion bisa jalan menyamping? Atau ada sesuatu yang terlewatkan di sini?

 

Oh ya, hasil akhir saya menang checkmate :)

Share this post: | | | |
Posted: Dec 18 2008, 10:19 AM by LonTonG | with 2 comment(s)
Filed under:
Setup & Deployment Dengan Visual Studio 2008

Minggu lalu saya coba memberikan software yang akan kami release dalam waktu dekat ini ke salah satu beta-tester external kami.
Cukup mengejutkan, teman kami langsung dihadiahi bonus error berikut saat menjalankan software yang akan ditest (beberapa informasi saya hapus, untuk kepentingan launching :) )

 

setup_error

 

Yang mengejutkan adalah bahwa hingga saat ini saya belom pernah mendapatkan masalah yang berkaitan dengan teknis distribusi software, karena software yang kami bangun langsung mengakses ke Win32 API, dan sangat minimal dengan dependensi dari programming language. Biasanya saya cukup memberikan file exe (dengan ukuran maksimal 500 kb) yang bisa langsung dijalankan (virtually everywhere), dan biasanya saya (juga terlihat pada screenshot di atas) letakan software di USB flash disk, sehingga portable bisa dibawa kemana - mana.

Nah, sekali ini kok bisa error?

Error ini cukup memakan waktu untuk sampai pada kesimpulan penyebab error, dan memang kalau dilihat pesan error nya sangat - sangat tidak intuitive.. Apa maksud dari application configuration is incorrect? Lebih lanjut.. saya harus reinstalling application? Halah!

Bandingkan dengan pesan error di bawah ini

 

intuitive_setup_error

 

Oh ya, ini software merupakan software perdana yang akan kami rilis yang dibangun dengan Microsoft Visual Studio 2008, sebelumnya kami menggunakan Visual Studio 6.

Terlebih dahulu saya pastikan bahwa kami tidak ceroboh dengan dynamically loaded library,walaupun seingat saya semuanya di-link statically, termasuk di dalamnya CRT. Saya coba gunakan tool dependency walker, eh kok ndak ada? biasanya dia ada dalam 1 paket dengan Visual Studio.. halah tambah ribet. Untungnya tool ini bisa didownload langsung di website nya. Ok, saya download, langsung saya jalankan.. dan hasilnya seperti di bawah. Tidak ada masalah.

 

depends_output

 

Lalu masalahnya di mana? Selidik punya selidik, ternyata ada file SxS assemblies (manifest and whatsoever) yang harus ditangani terlebih dahulu :(
Akhirnya terpaksa ngoprekin Setup & Deployment project di Visual Studio 2008.

Dibandingkan supaya bisa seperti di bawah ini (dan yang lainnya), saya lebih pilih portabilitas software.. cukup exe softwarenya saja, tanpa installer!

 

manifest_thinggy

Share this post: | | | |
Posted: Dec 10 2008, 01:02 PM by LonTonG | with 3 comment(s)
Filed under:
Blog Atau Theme Error?

Sepertinya ada yang aneh dengan blog geeks.netindonesia.net, waktu itu saya sendiri pernah bertanya - tanya kok bisa ya seperti ini:

 

index_screen

0 views, 3 comments

Bagaimana bisa seseorang memasukan komentar di salah satu post, tanpa terlebih dahulu melihat isi post tersebut? (mungkin ada shortcut?)

Saya mencoba sendiri dan hasilnya bisa dilihat dibawah ini:

 

control_panel_screen

 

Saat saya merubah theme ke theme tertentu, counter view post tidak berfungsi, namun begitu saya ganti theme lain, it works.

Saat ini yang saya duga bermasalah adalah theme snowflakes.

Share this post: | | | |
Posted: Nov 30 2008, 01:54 PM by LonTonG | with 4 comment(s)
Filed under:
C4996: Visual Studio Generated Warning Code

When you're working heavily with CRT library function, like fopen, strtok, etc, and you make a brave move to upgrade your development tool, let's say you want to move from Visual Studio 6 to Visual Studio 2008. After making adjustment here and there, you cross your finger, and then pressing Ctrl+Alt+F7. You might end up with soooo many horrible warnings, and one of them is C4996*.

1>.\Interface.c(1130) : warning C4996: 'strtok': This function or variable may be unsafe. Consider using strtok_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        C:\Program Files\Microsoft Visual Studio 9.0\VC\include\string.h(166) : see declaration of 'strtok'

What is this animal?

This is the explanation:

...

The compiler encountered a function that was marked with deprecated. The function may no longer be supported in a future release...

Some CRT and Standard C++ Library functions have been deprecated in favor of new, more secure functions.

...

So basically this warning warns you that you use deprecated function(s), and you should either replace that function to a new and more secure one, for example:

fopen with fopen_s

or if you're sure enough that your code couldn't be beaten up, you could simply ignore this warning by doing one of these:

1. #define _CRT_SECURE_NO_WARNINGS

2. #pragma warning(disable : 4996)

3. Lowering down you warning level (/W0 - /W2)

4. Or adding /wd4996


 

PS

* according to this article, C4996 warning only for level 1. I don't think this is right. I believe this is a warning for level >= 3 (default). If you do /W1 or even /W2, you won't get any of this warning.>

I see attempts, for example this one, to move this warning to a new level (level 5?), makes me wonder why would one want this?

Share this post: | | | |
Posted: Nov 26 2008, 08:21 AM by LonTonG | with no comments
Filed under: ,
Kocak Juga

Daripada mumet, iseng - iseng googling around.. eh ketemu situs ini, walaupun lumayan jadoel (2004?), tapi cukup menyegarkan juga hehe..

Cobain aja sendiri :)

This is what i got from "Which Nigerian Spammer Are You?" quiz:

You are Farouk Bello. You are Executive Director of Commercial Bank of Africa.  Your client was in a car accident along the shagamu express road.  You can't find his relatives so you want to share his $25.4 million with me. You require my positive response.

 

And I couldn't believe this!

 

Lumayan ngebuang 15 menit :D

Share this post: | | | |
Posted: Nov 10 2008, 02:29 PM by LonTonG | with no comments
Filed under:
More Posts « Previous page - Next page »