2010年12月22日星期三

用IOCTL_BEEP_SET控制System Buzzer

经测试,Vista SP1 32bits上系统蜂鸣器发出了声音。
此外,Vista 64bits, Windows 7上要么不发声音,要么是声卡发出声音。

// 以下宏定义摘自DDK中的头文件
#define FILE_DEVICE_BEEP                0x00000001

#define METHOD_BUFFERED                 0
#define METHOD_IN_DIRECT                1
#define METHOD_OUT_DIRECT               2
#define METHOD_NEITHER                  3

#define FILE_ANY_ACCESS                 0
#define FILE_READ_ACCESS          ( 0x0001 )    // file & pipe
#define FILE_WRITE_ACCESS         ( 0x0002 )    // file & pipe

#define CTL_CODE( DeviceType, Function, Method, Access ) (                 \
    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
    )

#define IOCTL_BEEP_SET \
    CTL_CODE(FILE_DEVICE_BEEP,0,METHOD_BUFFERED,FILE_ANY_ACCESS)


typedef struct _BEEP_SET_PARAMETERS {
    ULONG Frequency;
    ULONG Duration;
} BEEP_SET_PARAMETERS, *PBEEP_SET_PARAMETERS;

BOOL BeepSet (DWORD dwFreq, DWORD dwDuration)
{
    HANDLE hBeep;
    UNICODE_STRING BeepDevice;
    OBJECT_ATTRIBUTES ObjectAttributes;
    IO_STATUS_BLOCK IoStatusBlock;
    BEEP_SET_PARAMETERS BeepSetParameters;
    NTSTATUS Status;

    /* check the parameters */
    if ((dwFreq >= 0x25 && dwFreq <= 0x7FFF) ||
        (dwFreq == 0x0 && dwDuration == 0x0))
    {
        //      print(L"Beep Params OK\n");
        /* open the device */
        RtlInitUnicodeString(&BeepDevice,
            L"\\Device\\Beep");

        InitializeObjectAttributes(&ObjectAttributes,
            &BeepDevice,
            0,
            NULL,
            NULL);

        Status = NtCreateFile(&hBeep,
            FILE_READ_DATA | FILE_WRITE_DATA,
            &ObjectAttributes,
            &IoStatusBlock,
            NULL,
            0,
            FILE_SHARE_READ | FILE_SHARE_WRITE,
            FILE_OPEN_IF,
            0,
            NULL,
            0);
        if (NT_SUCCESS(Status))
        {
            //          print(L"Createfile worked\n");
            /* Set beep data */
            BeepSetParameters.Frequency = dwFreq;
            BeepSetParameters.Duration = dwDuration;

            Status = NtDeviceIoControlFile(hBeep,
                NULL,
                NULL,
                NULL,
                &IoStatusBlock,
                IOCTL_BEEP_SET,
                &BeepSetParameters,
                sizeof(BEEP_SET_PARAMETERS),
                NULL,
                0);

            /* do an alertable wait if necessary */
            if (NT_SUCCESS(Status) &&
                (dwFreq != 0x0 || dwDuration != 0x0) && dwDuration != (DWORD)-1)
            {
                //              print(L"Beep Sleeping\n");
                SleepEx(dwDuration,
                    TRUE);
            }

            NtClose(hBeep);
        }
    }
    else
        Status = STATUS_INVALID_PARAMETER;

    if (!NT_SUCCESS(Status))
    {
        //      SetLastErrorByStatus (Status);
        return FALSE;
    }

    return TRUE;
}

2010年11月26日星期五

outlook自动密送设置方法(2003~2010全适用)

outlook里面设置里面降低宏安全性;
重启outlook
Alt+F11后,选择左侧的thisoutlooksession,在弹出的窗口中加入以下内容:

Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
Dim objRecip As Recipient
Dim strMsg As String
Dim res As Integer
Dim strBcc As String
On Error Resume Next
strBcc = "***@gmail.com" '请改成你要密送的邮件地址
Set objRecip = Item.Recipients.Add(strBcc)
objRecip.Type = olBCC
If Not objRecip.Resolve Then
strMsg = "不能解析密件抄送人邮件地址, " & _
"请确认是否仍然发送邮件?"
res = MsgBox(strMsg, vbYesNo + vbDefaultButton1, _
"不能解析密件抄送人邮件地址")
If res = vbNo Then
Cancel = True
End If
End If
Set objRecip = Nothing
End Sub

保存即可。重启outlook即可。测试outlook2003~2010都没问题。
重点是要降低宏安全性,并适当重启。代码部分只需要修改红字部分即可。本文主要代码引自这里

2010年11月17日星期三

How to create a GIT web server on Linux

Orignal URL: http://www.kernel.org/pub/software/scm/git/docs/howto/setup-git-server-over-http.txt

Tags: GIT, Linux, Apache, WebDAV

===========================================
From: Rutger Nijlunsing <rutger@nospam.com>
Subject: Setting up a git repository which can be pushed into and pulled from over HTTP(S).
Date: Thu, 10 Aug 2006 22:00:26 +0200

Since Apache is one of those packages people like to compile
themselves while others prefer the bureaucrat's dream Debian, it is
impossible to give guidelines which will work for everyone. Just send
some feedback to the mailing list at git@vger.kernel.org to get this
document tailored to your favorite distro.


What's needed:

- Have an Apache web-server

On Debian:
$ apt-get install apache2
To get apache2 by default started,
edit /etc/default/apache2 and set NO_START=0

- can edit the configuration of it.

This could be found under /etc/httpd, or refer to your Apache documentation.

On Debian: this means being able to edit files under /etc/apache2

- can restart it.

'apachectl --graceful' might do. If it doesn't, just stop and
restart apache. Be warning that active connections to your server
might be aborted by this.

On Debian:
$ /etc/init.d/apache2 restart
or
$ /etc/init.d/apache2 force-reload
(which seems to do the same)
This adds symlinks from the /etc/apache2/mods-enabled to
/etc/apache2/mods-available.

- have permissions to chown a directory

- have git installed on the client, and

- either have git installed on the server or have a webdav client on
the client.

In effect, this means you're going to be root, or that you're using a
preconfigured WebDAV server.


Step 1: setup a bare GIT repository
-----------------------------------

At the time of writing, git-http-push cannot remotely create a GIT
repository. So we have to do that at the server side with git. Another
option is to generate an empty bare repository at the client and copy
it to the server with a WebDAV client (which is the only option if Git
is not installed on the server).

Create the directory under the DocumentRoot of the directories served
by Apache. As an example we take /usr/local/apache2, but try "grep
DocumentRoot /where/ever/httpd.conf" to find your root:

$ cd /usr/local/apache/htdocs
$ mkdir my-new-repo.git

On Debian:

$ cd /var/www
$ mkdir my-new-repo.git


Initialize a bare repository

$ cd my-new-repo.git
$ git --bare init


Change the ownership to your web-server's credentials. Use "grep ^User
httpd.conf" and "grep ^Group httpd.conf" to find out:

$ chown -R www.www .

On Debian:

$ chown -R www-data.www-data .


If you do not know which user Apache runs as, you can alternatively do
a "chmod -R a+w .", inspect the files which are created later on, and
set the permissions appropriately.

Restart apache2, and check whether http://server/my-new-repo.git gives
a directory listing. If not, check whether apache started up
successfully.


Step 2: enable DAV on this repository
-------------------------------------

First make sure the dav_module is loaded. For this, insert in httpd.conf:

LoadModule dav_module libexec/httpd/libdav.so
AddModule mod_dav.c

Also make sure that this line exists which is the file used for
locking DAV operations:

DAVLockDB "/usr/local/apache2/temp/DAV.lock"

On Debian these steps can be performed with:

Enable the dav and dav_fs modules of apache:
$ a2enmod dav_fs
(just to be sure. dav_fs might be unneeded, I don't know)
$ a2enmod dav
The DAV lock is located in /etc/apache2/mods-available/dav_fs.conf:
DAVLockDB /var/lock/apache2/DAVLock

Of course, it can point somewhere else, but the string is actually just a
prefix in some Apache configurations, and therefore the _directory_ has to
be writable by the user Apache runs as.

Then, add something like this to your httpd.conf

<Location /my-new-repo.git>
DAV on
AuthType Basic
AuthName "Git"
AuthUserFile /usr/local/apache2/conf/passwd.git
Require valid-user
</Location>

On Debian:
Create (or add to) /etc/apache2/conf.d/git.conf :

<Location /my-new-repo.git>
DAV on
AuthType Basic
AuthName "Git"
AuthUserFile /etc/apache2/passwd.git
Require valid-user
</Location>

Debian automatically reads all files under /etc/apache2/conf.d.

The password file can be somewhere else, but it has to be readable by
Apache and preferably not readable by the world.

Create this file by
$ htpasswd -c /usr/local/apache2/conf/passwd.git <user>

On Debian:
$ htpasswd -c /etc/apache2/passwd.git <user>

You will be asked a password, and the file is created. Subsequent calls
to htpasswd should omit the '-c' option, since you want to append to the
existing file.

You need to restart Apache.

Now go to http://<username>@<servername>/my-new-repo.git in your
browser to check whether it asks for a password and accepts the right
password.

On Debian:

To test the WebDAV part, do:

$ apt-get install litmus
$ litmus http://<servername>/my-new-repo.git <username> <password>

Most tests should pass.

A command line tool to test WebDAV is cadaver. If you prefer GUIs, for
example, konqueror can open WebDAV URLs as "webdav://..." or
"webdavs://...".

If you're into Windows, from XP onwards Internet Explorer supports
WebDAV. For this, do Internet Explorer -> Open Location ->
http://<servername>/my-new-repo.git [x] Open as webfolder -> login .


Step 3: setup the client
------------------------

Make sure that you have HTTP support, i.e. your git was built with
libcurl (version more recent than 7.10). The command 'git http-push' with
no argument should display a usage message.

Then, add the following to your $HOME/.netrc (you can do without, but will be
asked to input your password a _lot_ of times):

machine <servername>
login <username>
password <password>

...and set permissions:
chmod 600 ~/.netrc

If you want to access the web-server by its IP, you have to type that in,
instead of the server name.

To check whether all is OK, do:

curl --netrc --location -v http://<username>@<servername>/my-new-repo.git/HEAD

...this should give something like 'ref: refs/heads/master', which is
the content of the file HEAD on the server.

Now, add the remote in your existing repository which contains the project
you want to export:

$ git-config remote.upload.url \
http://<username>@<servername>/my-new-repo.git/

It is important to put the last '/'; Without it, the server will send
a redirect which git-http-push does not (yet) understand, and git-http-push
will repeat the request infinitely.


Step 4: make the initial push
-----------------------------

From your client repository, do

$ git push upload master

This pushes branch 'master' (which is assumed to be the branch you
want to export) to repository called 'upload', which we previously
defined with git-config.


Using a proxy:
--------------

If you have to access the WebDAV server from behind an HTTP(S) proxy,
set the variable 'all_proxy' to 'http://proxy-host.com:port', or
'http://login-on-proxy:passwd-on-proxy@proxy-host.com:port'. See 'man
curl' for details.


Troubleshooting:
----------------

If git-http-push says

Error: no DAV locking support on remote repo http://...

then it means the web-server did not accept your authentication. Make sure
that the user name and password matches in httpd.conf, .netrc and the URL
you are uploading to.

If git-http-push shows you an error (22/502) when trying to MOVE a blob,
it means that your web-server somehow does not recognize its name in the
request; This can happen when you start Apache, but then disable the
network interface. A simple restart of Apache helps.

Errors like (22/502) are of format (curl error code/http error
code). So (22/404) means something like 'not found' at the server.

Reading /usr/local/apache2/logs/error_log is often helpful.

On Debian: Read /var/log/apache2/error.log instead.

If you access HTTPS locations, git may fail verifying the SSL
certificate (this is return code 60). Setting http.sslVerify=false can
help diagnosing the problem, but removes security checks.


Debian References: http://www.debian-administration.org/articles/285

Authors
Johannes Schindelin <Johannes.Schindelin@gmx.de>
Rutger Nijlunsing <git@wingding.demon.nl>
Matthieu Moy <Matthieu.Moy@imag.fr>

2010年11月16日星期二

this指针为NULL的故障排除

问题来源,类成员函数相互调用时,突然在某成员函数入口处发现this指针为NULL,环境是Linux下的G++。

首先想到的是函数声明杂乱导致的堆栈错误,由于代码量大,一连查了好多天都没结果。

在Google上偶然发现了一个线索,可能是对象没有创建。
虽然看起来不像是这个原因,因为本来在类成员函数中运行的好好的,是执行到某处突然出现的问题。但在简单排查后确实发现这个类对象创建失败了,而且程序没有检查这个失败直接把对象指针当作有效值传进了函数。

总结一下,要是发现this指针为NULL,一定要检查一下这个对象是否已经创建。

2010年11月5日星期五

强制在当前窗口打开所有链接[FF]

Firefox配置

让所有网页链接都在当前也打开,避免出现新的TAB或WINDOW,如果需要在新TAB中打开的话,可以用右键菜单打开。

具体的配置方法,在地址栏敲入 about:config,(如果出现警告窗口的话请确认)。再在Filter中敲入newwindow,就可以看到下面两个配置项
browser.link.open_newwindow和browser.link.open_newwindow.restriction,双击修改值。

1. current, 2. tab, 3. window

把两个值都修改成 1 即可。

ref:http://www.ghacks.net/2009/07/03/force-firefox-to-open-links-in-same-tab/

2010年10月19日星期二

广域网的远程唤醒

广域网中实现远程唤醒,被控计算机端要增加一个能获取公网IP地址、能设置端口映射的设备(如路由器、防火墙)。

  1、在路由器中设置允许“Subnet Directed Broadcasts(子网定向广播)”,并且设置端口映射,将路由器的某一端口映射到被控计算机的任意端口 。

  2、只要路由器通电,主控计算机就能通过互联网向路由器发送Magic Packet,而路由器与被控计算机之间是通过网线连通的,所以可以很顺利地将Magic Packet发送到被控计算机的网卡。路由器实际上起到中间桥梁的作用。

  附上能发送Magic Packet的网页Wake On Lan over the Internet

  http://www.depicus.com/wake-on-lan/woli.aspx

  Netmask是一个比较值得注意的地方,填错了的话,目标IP地址就会出错。

  下面通过一个例子简单讲述一下广域网远程唤醒的过程

  假设主控计算机为A机,被控计算机为B机

  B机的所在局域网环境如下:一条ADSL接在4口路由器R1上,R1的4 个口分别连接着S1,S2,S3,S4四台交换机。B机接在S3交换机的其中一个口。

  R1拨号后自动获取到的IP为12.34.56.78,B机在局域网中的IP为192.168.1.167,MAC地址为BB:BB:BB:BB:BB:BB。

  在R1设置端口映射条目如下:12.34.56.78:9——>192.168.1.255:168

  这里192.168.1.255为192.168.1.167所在网络的定向广播地址。

  为什么不直接映射到192.168.1.167呢?因为当B机关机后,192.168.1.167这个IP不再与R1通信,R1中关于192.168.1.167的ARP条目也会很快就消失,所有与192.168.1.167这个IP通信的数据包都会被丢弃。

  1.A机向12.34.56.78(255.255.255.251)这个目标IP的9号端口发送一个包含FFFFFFFFFFFF和连续重复16次BBBBBBBBBBBB(为B的MAC地址)的Magic Packet的单播包,中间经过了N个路由,该单播包顺利进入R1;

  2.当R1检测到该数据包端口号为9,根据端口映射条目将该数据包的目标IP及端口号修改为192.168.1.255:168,此时该包被R1识别成定向广播包,因为R1已设置成允许Subnet Directed Broadcasts,所以该包并没有被丢弃;

  3.R1将这个广播包向4个口广播,S1,S2,S3,S4所连的所有端口都收到这个广播包,即便B机处于关机状态也会收到该广播包;

  B机的网卡检测到广播包中含自己MAC地址信息的Magic Packet,就会被唤醒,而其它机收到之后只会将该数据包丢弃。

  4.实际应用中不建议主控计算机通过IP地址去跟路由器通讯,因为一旦路由器重新获取IP地址,远程唤醒就会失效。只要路由器支持动态域名解析(DDNS)功能,可将路由设置成IP地址变更时自动向DDNS提供商重新注册IP地址,DDNS提供商将根据你的帐号对你申请的域名进行域名解析。设置成功后就可以通过固定的域名去与路由器通讯,唤醒与该路由器直连的计算机。