2012-12-29

2013 精简日历

Compact Calendar 2013 基础上:
  • 页面"Tables",增加了倒休日期功能
  • 页面"12-Month",以背景色区分工作日和节假日(休息日灰背景)
其他还有些小改动,主要是根据个人喜好修改了部分界面显示。

节假日安排依据国务院办公厅通知

=====8<=====8<=====8<=====8<=====8<=====8<=====8<=====8<=====8<=====

Based on Compact Calendar 2013:
  • On worksheet Tables, added Workday Lookup Table for workday shift
  • On worksheet 12-Month, distinguish workdays and holidays with different background color (white for workdays)
There might be some small changes on the display according to my own preference.

The holidays and workday shift are according to the government's announcement.

2012-09-13

退税,以及欧盟、欧元区、申根国的区别

主要参考:[實用資訊] 歐盟.歐元區.申根國傻傻分不清楚 暨 各種退稅方式

退税(有多种渠道和方式,我估计也就只会涉及下面两种):
* Global Blue 机场退税
* Amazon.de 网购退税
送货地址和账单(RECHNUNG)地址可以分开,账单地址需要为欧盟外国家或地区,邮寄地址可以为欧盟境内(免费送货)的地址。
拿着RECHNUNG在机场海关盖章。(机场海关还会再夹一张表格?)
将以下东西寄给Amazon.de:
原件:海关盖章的RECHNUNG
复印件:护照的首页、签证页、出入境页
地址如下:
Amazon.de
Umsatzsteuererstattung
Im Gewerbepark D 55
93059 Regensburg
Deutschland

申根(签证)主要是和出入境相关的。
欧盟主要和退税相关。
欧元区是指当地主要流通货币是欧元。

我在amazon.de据说和.uk, .us是一个账户;但和.cn的账户是用不了的)上注册了个账号,然后就退税提问,下面是回答的主体——应该是同一模版,没有细节,也没有回答我的具体问题。结合网上的一些中文信息,可以有个大体了解,可能实际操作也很简单、没有各种坑,就没有人有动力提供详细攻略了。

From: cs-reply@amazon.de
To qualify for the refund, the following legal deadline must be met: the item must be exported before the third calendar month following the month in which the goods were received has expired.

For legal reason, we require proof that:

*your residence is abroad (*non*EU) as far as this is not evident from the export certificate, and
*that the items you purchased from Amazon.de have been declared at the customs

Please send both documents as well as the original invoice (essential!) to the following address:

Amazon.de
Umsatzsteuererstattung
Im Gewerbepark D 55
93059 Regensburg
Deutschland

We will keep the original invoice and the confirmation for our records. If you need a copy of your invoices, please tell us the respective order numbers and we will send you the copies.

2012-07-17

Time sync issues - SQL Server login

There is weird problem occurred just yesterday: in the same domain, using the same domain account (Windows Authentication), but on two different computers, everything is fine on the first computer (which is the domain controller); but, one the other computer it is impossible to connect to SQL Server DB (which is also in the same domain).

We doubted our own program first, so we tried SQL Server Management Studio, and it also failed, mentioning "Failed to generate SSPI context".
Then, we switched from FQDN to IP address, succeeded but seems a little bit slower than normal.
So, we doubted the DNS server - running nslookup - but it's fine.

We compared every possible differences might exist between the two, finally there is the one: the second computer has the year as 2010 instead of 2012!
As it is a shared testing environment, it is hard to know and remember who did the change and why.

The reason is that for security the time is critical and a much longer one which is knowledge oriented not problem concentrated.
And this could be in a more subtle: different time zone showing the same time.

2012-06-25

Another time related issue - leap seconds

It is NTP, again.
Besides the integer overflow issue, not VM oriented, there is also leap seconds issue.

2012-06-15

Command Parameters and special characters

An elaborated article: http://www.autohotkey.net/~deleyd/parameters/parameters.htm

Howto change file ownership in command line or by programming

Q: Changing file Ownership with PowerShell 2.0
A: Setting the owner on an ACL in Powershell

A tool is also provided by MS: takeown. But the latest comment is very interesting: he/she ended up with Cygwin's chown.
Next time, I would try both :)

And Copy&Pasted the blog from cosmoskey.blogspot.com for reference:

==================================================================================================================

I was trying to set the owner of an ACL in powershell using the following code:

PS C:\Users\Johan> $acl = get-acl c:\temp\acltest
PS C:\Users\Johan> $principal = New-Object Security.Principal.NTAccount "$env:computername\ownertestaccount"
PS C:\Users\Johan> $acl.psbase.SetOwner($principal)
PS C:\Users\Johan> set-acl -Path C:\Temp\acltest -AclObject $acl
Set-Acl : The security identifier is not allowed to be the owner of this object.
At line:1 char:8
+ set-acl <<<<  -Path C:\Temp\acltest -AclObject $acl
    + CategoryInfo          : InvalidOperation: (C:\Temp\acltest:String) [Set-Acl], InvalidOperationException
    + FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.PowerShell.Commands.SetAclCommand


PS C:\Users\Johan>

So setting this ACL doesn't work. Why? I am an administrator! OK, what happens when I start the shell with Run As Administrator?... The same result.

So now we go to google and search a bit and I found the following KB article. What it says is that we need to have the rights to do the deed. Hey, not too surprising. By default Administrators and Backup Administrators have the Restore files and directories (SeRestorePrivilege) User Right. To set the owner we need to have this right, but in the scenario above I was executing the code with a account with all this privilege.

The problem here is that the privilege is not enabled in the access token, we need to call a function called AdjustTokenPrivileges() to adjust the current access token of our process. So we need to call this function, pass in a variable saying that we need to enable a privilege and pass in the privilege we want to enable. To call this function we need to do a little bit of PInvoke. I borrowed the base of my code from pinvoke.net.

So here is my little Set-Owner function.


function Set-Owner {
param(
[System.Security.Principal.IdentityReference]$Principal=$(throw "Mandatory parameter -Principal missing."),
$File=$(throw "Mandatory parameter -File missing.")
)
if(-not (Test-Path $file)){
throw "File $file is missing."
}
if($Principal -eq $null){
throw "Principal is NULL"
}


$code = @"
using System;
using System.Runtime.InteropServices;


namespace CosmosKey.Utils
{
public class TokenManipulator
{


[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);


[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern IntPtr GetCurrentProcess();


[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr
phtok);


[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool LookupPrivilegeValue(string host, string name,
ref long pluid);


[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct TokPriv1Luid
{
public int Count;
public long Luid;
public int Attr;
}


internal const int SE_PRIVILEGE_DISABLED = 0x00000000;
internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int TOKEN_QUERY = 0x00000008;
internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;


public const string SE_ASSIGNPRIMARYTOKEN_NAME = "SeAssignPrimaryTokenPrivilege";
public const string SE_AUDIT_NAME = "SeAuditPrivilege";
public const string SE_BACKUP_NAME = "SeBackupPrivilege";
public const string SE_CHANGE_NOTIFY_NAME = "SeChangeNotifyPrivilege";
public const string SE_CREATE_GLOBAL_NAME = "SeCreateGlobalPrivilege";
public const string SE_CREATE_PAGEFILE_NAME = "SeCreatePagefilePrivilege";
public const string SE_CREATE_PERMANENT_NAME = "SeCreatePermanentPrivilege";
public const string SE_CREATE_SYMBOLIC_LINK_NAME = "SeCreateSymbolicLinkPrivilege";
public const string SE_CREATE_TOKEN_NAME = "SeCreateTokenPrivilege";
public const string SE_DEBUG_NAME = "SeDebugPrivilege";
public const string SE_ENABLE_DELEGATION_NAME = "SeEnableDelegationPrivilege";
public const string SE_IMPERSONATE_NAME = "SeImpersonatePrivilege";
public const string SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege";
public const string SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege";
public const string SE_INC_WORKING_SET_NAME = "SeIncreaseWorkingSetPrivilege";
public const string SE_LOAD_DRIVER_NAME = "SeLoadDriverPrivilege";
public const string SE_LOCK_MEMORY_NAME = "SeLockMemoryPrivilege";
public const string SE_MACHINE_ACCOUNT_NAME = "SeMachineAccountPrivilege";
public const string SE_MANAGE_VOLUME_NAME = "SeManageVolumePrivilege";
public const string SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege";
public const string SE_RELABEL_NAME = "SeRelabelPrivilege";
public const string SE_REMOTE_SHUTDOWN_NAME = "SeRemoteShutdownPrivilege";
public const string SE_RESTORE_NAME = "SeRestorePrivilege";
public const string SE_SECURITY_NAME = "SeSecurityPrivilege";
public const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
public const string SE_SYNC_AGENT_NAME = "SeSyncAgentPrivilege";
public const string SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege";
public const string SE_SYSTEM_PROFILE_NAME = "SeSystemProfilePrivilege";
public const string SE_SYSTEMTIME_NAME = "SeSystemtimePrivilege";
public const string SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege";
public const string SE_TCB_NAME = "SeTcbPrivilege";
public const string SE_TIME_ZONE_NAME = "SeTimeZonePrivilege";
public const string SE_TRUSTED_CREDMAN_ACCESS_NAME = "SeTrustedCredManAccessPrivilege";
public const string SE_UNDOCK_NAME = "SeUndockPrivilege";
public const string SE_UNSOLICITED_INPUT_NAME = "SeUnsolicitedInputPrivilege";        


public static bool AddPrivilege(string privilege)
{
try
{
bool retVal;
TokPriv1Luid tp;
IntPtr hproc = GetCurrentProcess();
IntPtr htok = IntPtr.Zero;
retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.Luid = 0;
tp.Attr = SE_PRIVILEGE_ENABLED;
retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
return retVal;
}
catch (Exception ex)
{
throw ex;
}


}
public static bool RemovePrivilege(string privilege)
{
try
{
bool retVal;
TokPriv1Luid tp;
IntPtr hproc = GetCurrentProcess();
IntPtr htok = IntPtr.Zero;
retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.Luid = 0;
tp.Attr = SE_PRIVILEGE_DISABLED;
retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
return retVal;
}
catch (Exception ex)
{
throw ex;
}


}
}
}
"@


$errPref = $ErrorActionPreference
$ErrorActionPreference= "silentlycontinue"
$type = [CosmosKey.Utils.TokenManipulator]
$ErrorActionPreference = $errPref
if($type -eq $null){
add-type $code
}
$acl = Get-Acl $File
$acl.psbase.SetOwner($principal)
[void][CosmosKey.Utils.TokenManipulator]::AddPrivilege([CosmosKey.Utils.TokenManipulator]::SE_RESTORE_NAME)
set-acl -Path $File -AclObject $acl -passthru
[void][CosmosKey.Utils.TokenManipulator]::RemovePrivilege([CosmosKey.Utils.TokenManipulator]::SE_RESTORE_NAME)
}


If we run this function then we will see a very different result:

PS C:\Users\Johan> get-acl C:\Temp\acltest

    Directory: C:\Temp

Path               Owner                Access
----               -----                ------
acltest            MyLaptop\OldTest     BUILTIN\Administrators Allow  FullCo...


PS C:\Users\Johan> set-owner $(new-object security.principal.ntaccount "$env:computername\NewTest") C:\Temp\acltest

    Directory: C:\Temp

Path              Owner                Access
----              -----                ------
acltest           MyLaptop\NewTest     BUILTIN\Administrators Allow  FullCo...


PS C:\Users\Johan>

In the end we got there but it took me some time... :)