2009年4月21日星期二

发现一个文件上传的好网站

发现一个文件上传的好网站

http://www.uploadmirrors.com/

这个网站不错,以后可以将一些源代码传上去share

2009年4月13日星期一

最简单的WIN32多线程程序

最简单的WIN32多线程程序

这个例子来自MSDN







    1 // crt_begthrdex.cpp
    2 // compile with: /MT
    3 #include <windows.h>
    4 #include <stdio.h>
    5 #include <process.h>
    6 
    7 unsigned Counter; 
    8 unsigned __stdcall SecondThreadFunc( void* pArguments )
    9 {
   10     printf( "In second thread...\n" );
   11 
   12     while ( Counter < 1000000 )
   13         Counter++;
   14 
   15     _endthreadex( 0 );
   16     return 0;
   17 } 
   18 
   19 int main()
   20 { 
   21     HANDLE hThread;
   22     unsigned threadID;
   23 
   24     printf( "Creating second thread...\n" );
   25 
   26     // Create the second thread.
   27     hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0, &threadID );
   28 
   29     // Wait until second thread terminates. If you comment out the line
   30     // below, Counter will not be correct because the thread has not
   31     // terminated, and Counter most likely has not been incremented to
   32     // 1000000 yet.
   33     WaitForSingleObject( hThread, INFINITE );
   34     printf( "Counter should be 1000000; it is-> %d\n", Counter );
   35     // Destroy the thread object.
   36     CloseHandle( hThread );
   37 }


2009年4月10日星期五

Enum Registry SubKeys in JScript

Enum Registry SubKeys in JScript

I have searched for a good solution to enum the registries with JScript for a long time. Today I got it. The original url is http://www.msghelp.net/showthread.php?tid=65331&page=1 .

The two functions are as below:

 
function EnumSubKeys(RegKey) {
    var RootKey = new Object()
    RootKey["HKCR"] = RootKey["HKEY_CLASSES_ROOT"] = 0x80000000;
    RootKey["HKCU"] = RootKey["HKEY_CURRENT_USER"] = 0x80000001;
    RootKey["HKLM"] = RootKey["HKEY_LOCAL_MACHINE"] = 0x80000002;
    RootKey["HKUS"] = RootKey["HKEY_USERS"] = 0x80000003;
    RootKey["HKCC"] = RootKey["HKEY_CURRENT_CONFIG"] = 0x80000005;
    var RootVal = RootKey[RegKey.substr(0, RegKey.indexOf("\\"))]
    if (RootVal != undefined) {
        Locator = new ActiveXObject("WbemScripting.SWbemLocator");
        ServerConn = Locator.ConnectServer(null, "root\\default");
        Registry = ServerConn.Get("StdRegProv");
        Method = Registry.Methods_.Item("EnumKey");
        p_In = Method.InParameters.SpawnInstance_();
        p_In.hDefKey = RootVal;
        p_In.sSubKeyName = RegKey.substr(RegKey.indexOf("\\") + 1)
        p_Out = Registry.ExecMethod_(Method.Name, p_In);
        return p_Out.sNames.toArray();
    }
}
 
 
function EnumValues(RegKey) {
    var RootKey = new Object()
    RootKey["HKCR"] = RootKey["HKEY_CLASSES_ROOT"] = 0x80000000;
    RootKey["HKCU"] = RootKey["HKEY_CURRENT_USER"] = 0x80000001;
    RootKey["HKLM"] = RootKey["HKEY_LOCAL_MACHINE"] = 0x80000002;
    RootKey["HKUS"] = RootKey["HKEY_USERS"] = 0x80000003;
    RootKey["HKCC"] = RootKey["HKEY_CURRENT_CONFIG"] = 0x80000005;
    var RootVal = RootKey[RegKey.substr(0, RegKey.indexOf("\\"))]
    if (RootVal != undefined) {
        Locator = new ActiveXObject("WbemScripting.SWbemLocator");
        ServerConn = Locator.ConnectServer(null, "root\\default");
        Registry = ServerConn.Get("StdRegProv");
        Method = Registry.Methods_.Item("EnumValues");
        p_In = Method.InParameters.SpawnInstance_();
        p_In.hDefKey = RootVal;
        p_In.sSubKeyName = RegKey.substr(RegKey.indexOf("\\") + 1)
        p_Out = Registry.ExecMethod_(Method.Name, p_In);
        return p_Out.sNames.toArray();
    }
}



The test code is following


var
Shell = new ActiveXObject("WScript.Shell")
var Key = "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"
var ValuesArray = EnumValues(Key);
WScript.StdOut.WriteLine("=== Global startup ===")
for (Index in ValuesArray) {
    var ValueName = ValuesArray[Index]
    ValueValue = Shell.RegRead(Key + "\\" + ValueName)
    WScript.StdOut.WriteLine(ValueName + " = " + ValueValue)
}
var Key = "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
var ValuesArray = EnumSubKeys(Key);
WScript.StdOut.WriteLine("=== Uninstall startup ===")
for (Index in ValuesArray) {
    var ValueName = ValuesArray[Index]
    WScript.StdOut.WriteLine(ValueName);
}



2009年4月8日星期三

Edit控件的字体和颜色











Edit控件的字体和颜色

字体可以采用函数CreateFont来创建,如下面的例子所示


        CFont fnt;
        fnt.CreateFont(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, 
OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, _T("Lucida Console"));
        m_Edit.SetFont(fnt);
        fnt.Detach();


Edit控件的字体颜色,背景颜色需要在父窗口中处理消息WM_CTLCOLOREDIT,如下面的函数所示:


    LRESULT OnCtlColorEdit(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        CDC  dc((HDC)wParam);
        HWND hwnd = (HWND)lParam;
        HBRUSH hbr = 0;
 
        if (m_Edit.m_hWnd == hwnd)
        {
            dc.SetTextColor(RGB(192,192,192));
            dc.SetBkColor(RGB(0,0,0));
            hbr = CreateSolidBrush(RGB(0,0,0));
            bHandled = TRUE;
        }
        else
            bHandled = FALSE;
 
        dc.Detach();
 
        return (LRESULT)hbr;
    }


参考:http://forums.devx.com/showthread.php?t=83993

2009年4月2日星期四

WriteFile,WriteConsole和_tprintf的一些差别
















WriteFile,WriteConsole和_tprintf的一些差别

这几个API都是用于输出的,但都有各自的特点:
1. _tprintf的实现利用了WriteFile和WideCharToMultiByte。
2. WriteFile只接受字节流,没有UNICODE的概念,WriteFile可以实现重定向。
3. WriteConsole有两个版本WriteConsoleA和WriteConsoleW, 可以分别接收ANSI和UNICODE字符串,不支持重定向。


看下面这个简单的程序,编译后再用eXeScope分析一下Import

    1 #include <stdio.h>
    2 
    3 void wmain(int argc, wchar_t* argv[])
    4 {
    5     wprintf(L"Hello World\n");
    6 }

看了eXeScope的输出后,发现wprintf的实现利用了WideCharToMultiByte和WriteFile等API,在写入文件前首先是将UNICODE转换成多字节的。


然后本人试着直接调用API进行输出,分别使用了API WriteConsole和WriteFile
 
    1 #include <windows.h>
    2 
    3 #pragma comment(lib, "User32")
    4 #pragma comment(lib, "Kernel32")
    5 #pragma comment(linker, "/Entry:wmain")
    6 #pragma comment(linker, "/Merge:.rdata=.text")
    7 
    8 void *operator new[](unsigned int size){
    9     return HeapAlloc (GetProcessHeap(), NULL, size);
   10 }
   11 
   12 void operator delete[] (void* memblock){
   13     HeapFree (GetProcessHeap(), NULL, memblock);
   14 }
   15 
   16 bool WINAPI StdOut( wchar_t* lpString)
   17 {
   18     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
   19     DWORD numOfCharsWritten=0;
   20     WriteConsole(hStdOut, lpString, lstrlen(lpString), &numOfCharsWritten, NULL);
   21 
   22     DWORD dwNum = WideCharToMultiByte(CP_OEMCP,NULL,lpString, -1, NULL, 0, NULL, false);
   23     char *pText = new char[dwNum];
   24     WideCharToMultiByte(CP_OEMCP,NULL,lpString,-1,pText,dwNum,NULL,false);
   25     BOOL bRet = WriteFile(hStdOut, pText, dwNum, &numOfCharsWritten, NULL);
   26     delete[] pText;
   27     return bRet;
   28 }
   29 
   30 void wmain()
   31 {
   32     wchar_t *pChar = L"Hello World!\n";
   33     StdOut(pChar);
   34 }

命令行编译 cl client.cpp /DUNICODE /D_UNICODE /LINK /ALIGN:16
程序执行结果为:
Hello World!
Hello World!


下面的程序Parent.cpp用于输出重定向


    1 #include "stdafx.h"
    2 #include <windows.h>
    3 #include <tchar.h>
    4 #include <stdio.h>
    5 
    6 HANDLE SpawnAndRedirect(LPCTSTR commandLine, HANDLE *hStdOutputReadPipe, LPCTSTR lpCurrentDirectory);
    7 
    8 int _tmain()
    9 {
   10     HANDLE hOutput, hProcess;
   11     hProcess = SpawnAndRedirect(_T("client.exe"), &hOutput, NULL);
   12     if (!hProcess){
   13         _tprintf(_T("Failed to spawn the thread\n"));
   14         return 1;
   15     }
   16 
   17     char buffer[129];
   18     DWORD read;
   19     while(ReadFile(hOutput, buffer, 128, &read, NULL))
   20     {
   21         buffer[read] = '\0';
   22         printf("%s\n", buffer);
   23     }
   24 
   25     CloseHandle(hOutput);
   26     CloseHandle(hProcess);
   27 
   28     return 0;
   29 }
   30 
   31 
   32 // The following function is a shortened variant of Q190351 - HOWTO: Spawn Console Processes with Redirected Standard Handles
   33 // There is no special magic here, and this version doesn't address issues like:
   34 // - redirecting Input handle
   35 // - spawning 16-bits process 
   36 // - command-line limitations (unsafe 1024-char buffer)
   37 // So you might want to use more advanced versions such as the ones you can find on CodeProject
   38 HANDLE SpawnAndRedirect(LPCTSTR commandLine, HANDLE *hStdOutputReadPipe, LPCTSTR lpCurrentDirectory)
   39 {
   40     HANDLE hStdOutputWritePipe, hStdOutput, hStdError;
   41     CreatePipe(hStdOutputReadPipe, &hStdOutputWritePipe, NULL, 0);  // create a non-inheritable pipe
   42     DuplicateHandle(GetCurrentProcess(), hStdOutputWritePipe,
   43         GetCurrentProcess(), &hStdOutput,                           // duplicate the "write" end as inheritable stdout
   44         0, TRUE, DUPLICATE_SAME_ACCESS);
   45     DuplicateHandle(GetCurrentProcess(), hStdOutput,
   46         GetCurrentProcess(), &hStdError,                            // duplicate stdout as inheritable stderr
   47         0, TRUE, DUPLICATE_SAME_ACCESS);
   48     CloseHandle(hStdOutputWritePipe);                               // no longer need the non-inheritable "write" end of the pipe
   49 
   50     PROCESS_INFORMATION pi;
   51     STARTUPINFO si;
   52     ZeroMemory(&si, sizeof(STARTUPINFO));
   53     si.cb = sizeof(STARTUPINFO);
   54     si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
   55     si.hStdInput  = GetStdHandle(STD_INPUT_HANDLE); // (this is bad on a GUI app)
   56     si.hStdOutput = hStdOutput;
   57     si.hStdError  = hStdError;
   58     si.wShowWindow = SW_HIDE;                       // IMPORTANT: hide subprocess console window
   59     TCHAR commandLineCopy[1024];                    // CreateProcess requires a modifiable buffer
   60     _tcscpy(commandLineCopy, commandLine);
   61     if (!CreateProcess(    NULL, commandLineCopy, NULL, NULL, TRUE,
   62         CREATE_NEW_CONSOLE, NULL, lpCurrentDirectory, &si, &pi))
   63     {
   64         CloseHandle(hStdOutput);
   65         CloseHandle(hStdError);
   66         CloseHandle(*hStdOutputReadPipe);
   67         *hStdOutputReadPipe = INVALID_HANDLE_VALUE;
   68         return NULL;
   69     }
   70 
   71     CloseHandle(pi.hThread);
   72     CloseHandle(hStdOutput);
   73     CloseHandle(hStdError);
   74     return pi.hProcess;
   75 }


调用Parent,这个程序会创建子进程Client,并且通过pipe将Client的输出定向为Parent的输出,程序的执行结果为
Hello World!
在Client中WriteConsole的输出没有重定向过来!