Archive for the ‘ windows ’ Category

IE6と7以降でIEキャッシュの命名規則が違う

http://127.0.0.1/ のようなURLにキャッシュ可能な文書を置いてアクセスし、Temporary Internet Files に生成されるファイル名を確認すると、

  • IE6 では、 127.0.0.1[1].txt となる
  • IE7/8 では、 127_0_0_1[1].txt となる

なんて微妙な仕様変更。

SDカードから失われた動画を復旧する

ffmpeg で -i オプションにワイルドカードを使ったらSDカード内のAVIがごっそり0バイトになって焦った。

ここは本気を出さねばならない。

selfImageで、メディアまるごとのバイナリイメージを取って、以下のコードを実行し、「”RIFF”から始まるファイル」に分割。なんせ元のファイルサイズが失われてるのでほんとはきちんとRIFFフォーマットを解析しなきゃならないのだが、面倒なので。

あとは、出来上がった「後ろにおまけのついた動画ファイル」を無理やり動画コンバータに放り込んで変換成功。

ふぅ、冷汗かいた。

int _tmain(int argc, _TCHAR* argv[])
{
char buf[BUF_SIZE];
FILE* fp;
::fopen_s(&fp, "sd_card.img", "rb");
FILE* fOut=NULL;
int count=0;
while(!::feof(fp)){
::fread(buf, 1, BUF_SIZE, fp);
if(fOut)::fwrite(buf, 1, BUF_SIZE,fOut);
long cur=0;
while(cur<BUF_SIZE){
const char* pos=(const char*)::memchr(buf+cur, 'R', BUF_SIZE-cur);
if(!pos){
break;
}
if(::memcmp(pos, "RIFF", 4)==0){
if(fOut)::fclose(fOut);
char fname[20];
::sprintf(fname, "%d.avi", count);
fOut=::fopen(fname, "wb");
::fwrite(pos, 1, BUF_SIZE-(pos-buf), fOut);
count++;
}
cur=pos-buf+1;
}
}
if(fOut)::fclose(fOut);
::fclose(fp);
return 0;
}

substとショートカットの怪しい関係

  1. substでドライブ作る
  2. 出来たドライブへのショートカットを作る
  3. subst /dでドライブを消す
  4. さっき作ったショートカットのリンク先がいつの間にか変わる。

きもーい。

PathMatchSpecの挙動

Windows上でワイルドカードを処理するAPIがPathMatchSpecである。

http://msdn.microsoft.com/en-us/library/bb773727(VS.85).aspx

しかしここに載っているサンプルがあまりにもセンスが悪い。

ということでテストコードを書いた。コードは後述。結果は以下。

"somepath.html" , "somepath?html" => true
"somepath.html" , "" => true
"somepath.html" , "(null)" => false
"" , "*" => true
"" , "a" => false
"somepath" , "*." => false
"somepath" , "*.*" => true
"hoge\fuga.html" , "hoge*" => true
"hoge\fuga.html" , "hoge*html" => true
"hoge\fuga.html" , "hoge\*" => true

コードはこんな。

#include <stdio.h>
#include <Shlwapi.h>
#pragma comment(lib, "shlwapi.lib")
void test(const wchar_t* path, const wchar_t* spec){
wprintf(L"\"%s\" , \"%s\" => %s\n"
, path, spec
, ::PathMatchSpec(path, spec)?L"true":L"false");
}
int main(const int &){
test(L"somepath.html", L"somepath?html");
test(L"somepath.html", L"");
test(L"somepath.html", NULL);
test(L"", L"*");
test(L"", L"a");
test(L"somepath", L"*.");
test(L"somepath", L"*.*");
test(L"hoge\\fuga.html", L"hoge*");
test(L"hoge\\fuga.html", L"hoge*html");
test(L"hoge\\fuga.html", L"hoge\\*");
}

WM_GETDLGCODE無限ループ:2

d:id:kuboon:20090901

なんだかいろんな人がいろんなことを言っているが、

http://www.tech-archive.net/Archive/InetSDK/microsoft.public.inetsdk.programming.webbrowser_ctl/2006-06/msg00038.html

に載っていたコードが実装しやすそうだったので入れてみたら直った。

一度直ればこっちのもんで、コード修正と実行を繰り返し、最終的に落ち着いたのは以下のコード。

LRESULT BrowserDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if( (message==WM_SYSCOMMAND && wParam==SC_MINIMIZE) //最小化ボタン
||  (message==WM_ACTIVATE && wParam==WA_INACTIVE)   //フォーカスアウト
||  (message==WM_SHOWWINDOW && wParam==FALSE)		//不可視化
){
::SetFocus(NULL);
}
return CDialog::WindowProc(message, wParam, lParam);
}

WM_GETDLGCODE無限ループ

IWebBrowserを乗っけたダイアログ上でJavaAppletを開き、アプレット上のUIをいじっているとメインスレッドがフリーズ。

なんだろうと思ってブレークをかけてみると、ダイアログの子要素に対してWM_GETDLGCODEがものすごい勢いで投げまくられている状態。

で、調査した。

WM_GETDLGCODEのなんたるか:

http://msdn.microsoft.com/ja-jp/library/ms645425

http://support.microsoft.com/kb/83302/en

タブコントロールを使っている場合に同じ状況に陥るケースが頻繁に報告されている。僕には関係ない。次。

http://blog.goo.ne.jp/satomi_takeo/e/b058ef705da6ca88ec87db660878c789

あたりっぽいんだが、リンク先サイトが死んでいて状況を追えず。次。

http://www.guyswithtowels.com/articles/2002-08-15-1600.html#ModelessDialogs

具体的なコードも出ていて助かる。が、メッセージポンプはMFC側にあるので、この通りに実装するの難しそう。

LVIS_DROPHILITED?

HILIGHTED だろJK.

MSXMLで文字列をインポートする方法

loadXMLを使うと encoding が期待通り処理されない。

以下のようにする。

VARIANT var;
{
SAFEARRAYBOUND	rgb={strlen(xml),0}; //末尾にNULL文字つけちゃだめ
SAFEARRAY* psa = SafeArrayCreate(VT_UI1,1, &rgb);
if(!psa){
assert(false);
return false;
}
char*	buf;
SafeArrayAccessData(psa,(void**)&buf);	// 作成したSAFEARRAYのポインタ取得及びロック
memcpy(buf,xml,strlen(xml)); // 末尾のNULL文字分のバッファは無い!
SafeArrayUnaccessData(psa);		// アンロック
var.vt=VT_ARRAY|VT_UI1;
var.parray=psa;
}
bool ret=manifest->load(var);
::SafeArrayDestroy(var.parray);
if(!ret){
::OutputDebugString(manifest->GetparseError()->Getreason());
::OutputDebugString(manifest->GetparseError()->GetsrcText());
return false;
}

末尾にNULLが付いているとパースエラーになるのが落とし穴。

WM_GETDLGCODE無限ループ

IWebBrowserを乗っけたダイアログ上でTextFieldを含んだJavaAppletを開き、そのあたりをいじっているとメインスレッドがフリーズ。

なんだろうと思ってブレークをかけてみると、ダイアログの子要素に対してWM_GETDLGCODEがものすごい勢いで投げまくられている状態。

で、調査した。

WM_GETDLGCODEのなんたるか:

http://msdn.microsoft.com/ja-jp/library/ms645425

http://support.microsoft.com/kb/83302/en

タブコントロールを使っている場合に同じ状況に陥るケースが頻繁に報告されている。僕には関係ない。次。

http://blog.goo.ne.jp/satomi_takeo/e/b058ef705da6ca88ec87db660878c789

あたりっぽいんだが、リンク先サイトが死んでいて状況を追えず。次。

http://www.guyswithtowels.com/articles/2002-08-15-1600.html#ModelessDialogs

具体的なコードも出ていて助かる。が、メッセージポンプはMFC側にあるので、この通りに実装するの難しそう。

JobObject の壁

複数のプロセスをまとめて管理する仕組みとしてJobObjectというものがある。

http://msdn.microsoft.com/en-us/library/ms684161(VS.85).aspx

POSIX準拠の仕組みらしく、古くはapacheのようなヤツがいくつかのプロセスを立ち上げて堅牢性を向上させていたり、最近はGoogle Chromeなどでも使われている。

SetInformationJobObject のリファレンスを見ると、

http://msdn.microsoft.com/en-us/library/ms686216(VS.85).aspx

JobObjectに対して様々な制約をかけることができることが分かる。

例えば、総プロセッサ時間、総メモリ消費量のようなものだ。

その他に、JOB_OBJECT_UILIMIT_DISPLAYSETTINGS, JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS のようなものもあり、ジョブ配下のプロセスがシステム全体に影響を及ぼすことがないようにする仕組みと考えられる。

VISTAではすべてのプロセスは Explorer のジョブグループに属してしまうようだ。(しかもProcessExplorerでも見えない?)

CREATE_BREAKAWAY_FROM_JOB を使って新規プロセスを作ると、そこでは AssignProcessToJobObject が成功する。

UACのせいだとかいろんなことを言っている人がいるが、たぶん間違い。

http://social.msdn.microsoft.com/Forums/en-US/windowssecurity/thread/71c9599e-a3d5-4b79-bfc1-1800565c5b8a

だって REATE_BREAKAWAY_FROM_JOB だけで出来たもん。

で、どこにも書いてないけどほかにも様々な壁があるっぽい。

  • SHAppBarMessage が利かない。ウィンドウハンドルが別扱いになるからかな?
  • CHtmlView を利用したブラウザが、PowerPoint等を開くとき、powerpnt.exe はDCOM経由で立ち上がるためにJobObjectに加わらない。で、たぶんそのウィンドウがブラウザから制御できないため、MFC内でクラッシュする。致命的。
  • RegisterWindowMessage が別になる
  • Jobの外でコピーしたデータをジョブの中へペースト出来ない。逆はできるっぽい。