warning C4305:
先日次の様なコードを書いていた.塗りつぶして表示する時の色の補正.
ColorRGB colRGB = ::ColorRefToRGB(pgs1.GetColor()) ;
{
float rgbcol = colRGB.R + colRGB.G + colRGB.B ;
if (rgbcol < 0.20*3) {
if (colRGB.R < 0.20) { colRGB.R = 0.20f ; }
if (colRGB.G < 0.20) { colRGB.G = 0.20f ; }
if (colRGB.B < 0.20) { colRGB.B = 0.20f ; }
}
if (0.80*3 < rgbcol) {
if (0.80 < colRGB.R) { colRGB.R = 0.80f ; }
if (0.80 < colRGB.G) { colRGB.G = 0.80f ; }
if (0.80 < colRGB.B) { colRGB.B = 0.80f ; }
}
}
ColorRGB.R などは float で,RGB のそれぞれを 0.0 ~ 1.0 で表現したもの.
最初 if (colRGB.R < 0.25) { colRGB.R = 0.25 ; } の様にしていたが,0.2 に変更した.
すると C4305 の warning .0.2f の様にすれば良いのはわかっているが,他の値で調べてみた.
0.0 , 1.0 , 7.0 などは大丈夫だが,0.2 や 7.1 は C4305 になってしまう.
コンパイラやオプションの指定にもよると思うが,float で表現できない場合のみ warning となるのか?
SetForegroundWindow
他 AP から,HWND を指定して前面に移動する方法.
bool Window_Foreground (HWND hWnd)
{
if (hWnd == NULL) { return false ; }
if (!::IsWindow(hWnd)) { return false ; }
{
if (::IsIconic(hWnd)) {
WINDOWPLACEMENT wndpl = { 0 } ;
::GetWindowPlacement(hWnd,&wndpl) ;
wndpl.showCmd = SW_RESTORE ;
::SetWindowPlacement(hWnd,&wndpl) ;
}
SetForegroundWindow(hWnd) ;
}
return true ;
}
ゼロからの OS 自作入門 第 3 章
main.cpp のコンパイル,リンク.
$ cd ~/workspace/mikanos
$ git checkout osbook_day03a
$ cd kernel
$ clang++ -O2 -Wall -g –target=x86_64-elf -ffreestanding -mno-red-zone -fno-exceptions -fno-rtti -std=c++17 -c main.cpp
$ ld.lld –entry KernelMain -z norelro –image-base 0x100000 –static -o kernel.elf main.o
ブートローダのビルドと実行.
$ cd ~/edk2
$ source edksetup.sh
$ build
$ ~/osbook/devenv/run_qemu.sh Build/MikanLoaderX64/DEBUG_CLANG38/X64/Loader.efi ~/workspace/mikanos/kernel/kernel.elf
うまくいっているのか,ちょっとわからず.
2023/06/15
$ cd ~/workspace/mikanos
$ git checkout osbook_day03b
$ cd ~/edk2
$ source edksetup.sh
$ build
$ ~/osbook/devenv/run_qemu.sh Build/MikanLoaderX64/DEBUG_CLANG38/X64/Loader.efi ~/workspace/mikanos/kernel/kernel.elf
$ cd ~/workspace/mikanos
$ git checkout osbook_day03c
$ source ~/osbook/devenv/buildenv.sh
$ cd ~/workspace/mikanos/kernel/
$ clang++ $CPPFLAGS -O2 –target=x86_64-elf -fno-exceptions -ffreestanding -c main.cpp
$ ld.lld $LDFLAGS –entry KernelMain -z norelro –image-base 0x100000 –static -o kernel.elf main.o
$ cd ~/edk2
$ source edksetup.sh
$ build
$ ~/osbook/devenv/run_qemu.sh Build/MikanLoaderX64/DEBUG_CLANG38/X64/Loader.efi ~/workspace/mikanos/kernel/kernel.elf
これもうまく動作しない.どうも kernel の呼出しがうまく行っていない?
ゼロからの OS 自作入門 第 2 章
本にある通り
$ cd ~/workspace/mikanos
$ git checkout osbook_day02a
$ cd ~/edk2
$ ln -s ~/workspace/mikanos/MikanLoaderPkg ./
$ source edksetup.sh
$ build
Conf/target.txt を「表 2.1」に変更しなければならない?
すると今度は…
build.py...
/home/iwao/edk2/MikanLoaderPkg/MikanLoaderPkg.dsc(...): error 4000: Instance of library class [RegisterFilterLib] is not found
in [/home/iwao/edk2/MdePkg/Library/BaseLib/BaseLib.inf] [X64]
consumed by module [/home/iwao/edk2/MikanLoaderPkg/Loader.inf]
「error 4000: Instance of library class [RegisterFilterLib] is not found」で検索すると
FAQ(よくある質問とその回答)
次の方法で対応.
$ git checkout 38c8be123aced4cc8ad5c7e0da9121a181b94251
うまくビルドできた.
$ cd ~/workspace/mikanos/
$ git checkout osbook_day02b
$ cd ~/edk2/
$ source edksetup.sh
$ build
$ cd Build/MikanLoaderX64/DEBUG_CLANG38/X64/
$ ~/osbook/devenv/run_qemu.sh ./Loader.efi
QNAP NAS 証明書の更新
QNAP NAS の Let’s Encrypt での証明書の更新が安定しない.
以前は,自動で更新できていた頃もあったと思う.
手動で「証明書更新」としても,うまく更新できない.
今回は,代替名の ts.mish.work を外して,証明書を取得することができた.
ゼロからの OS 自作入門 第 1 章
昨日 VirtualBox 内の Ubuntu の QEMU が動作することは確認できたので,バイナリコードの入力から.
hello.c をコピー.EfiMain() の while(1) ; のループをコメントにして,コンパイル,リンクしたものを実行.
EfiMain() を起動した後,BIOS の画面に入った?
VC 2022 17.6.?
先日 VS 2022 の更新版 があったのでアップデート.
個人的なツールの 3D ビューア をビルドすると,
ALYac Gen:Variant.Tedy.373496
Arcabit Trojan.Tedy.D5B2F8
BitDefender Gen:Variant.Tedy.373496
Cylance Unsafe
DeepInstinct MALICIOUS
Emsisoft Gen:Variant.Tedy.373496 (B)
eScan Gen:Variant.Tedy.373496
GData Gen:Variant.Tedy.373496
MAX Malware (ai Score=81)
McAfee Artemis!AE3A9CE560AE
McAfee-GW-Edition Artemis
Trellix (FireEye) Gen:Variant.Tedy.373496
TrendMicro-HouseCall TROJ_GEN.R002H09EQ23
VIPRE Gen:Variant.Tedy.373496
VC 2019 などでビルドしたものは問題ない.また VC 2022 更新前のものも問題なかった.
今まで VS の更新版が出てすぐにそれでビルドすることは少なかった.
テストが不十分なこともあり,リリース用は主に VC 2017 を使用している.
更新版によっては,この様なことがあるのかもしれない.
落ち着くまでしばらく時間がかかるのか?
ゼロからの OS 自作入門
久しぶりにいい本(自分に合っている本)を購入.
まだ第1章までしか読めていないが,知らないことがいっぱい.
https://zero.osdev.jp/
https://zero.osdev.jp/book-sample.pdf
1 日に 1 章をクリアしていけば,ほぼ 1ヶ月で消化できるみたいだが,そこまでは時間が取れないか?
2023/05/30
少し時間がかかったが,VirtuaBox 内の Ubuntu 22.04.2 LTS に環境を作成した.
確認用 PC 環境は,その Ubuntu 内の QEMU .
手順は,次の所に書かれている通りで,付録 A の状態に.
https://github.com/uchan-nos/mikanos-build
$ cd $HOME
$ git clone https://github.com/uchan-nos/mikanos-build.git osbook
$ sudo apt install ansible
$ cd $HOME/osbook/devenv
$ ansible-playbook -K -i ansible_inventory ansible_provision.yml
これで,QEMU も入るみたいで /usr/bin/ 以下に qemu-* が存在する.
35 ページに書かれている方法でやってみたがうまくいかず,そのページの下の方の run_qemu.sh を使用した.
error during ReadSymbolTable
5 年位前に作成したプロジェクトをビルドしていると,
--------------------Configuration: phpup_mb - Win32 Debug--------------------
Compiling...
ComPrj01.cpp
phpup_mb.cpp
...
Linking...
c:\Temp\HTM\phpup\phpup_mb\Debug.060\ComPrj01.obj : error : Internal error during ReadSymbolTable
ExceptionCode = C0000005
ExceptionFlags = 00000000
ExceptionAddress = 004623F2
NumberParameters = 00000002
ExceptionInformation[ 0] = 00000000
ExceptionInformation[ 1] = 0090B470
CONTEXT:
Eax = 3FFF1E64 Esp = 0019F050
Ebx = FFFF8000 Ebp = 01B834C7
Ecx = 3FFF1E64 Esi = 401F1EC0
Edx = 0094B478 Edi = 401F1EC0
Eip = 004623F2 EFlags = 00010246
SegCs = 00000023 SegDs = 0000002B
SegSs = 0000002B SegEs = 0000002B
SegFs = 00000053 SegGs = 0000002B
Dr0 = 0019F050 Dr3 = FFFF8000
Dr1 = 01B834C7 Dr6 = 3FFF1E64
Dr2 = 00000000 Dr7 = 00000000
Error executing link.exe.
Tool execution canceled by user.
exe は存在するが正しくできていないので,exe のみ削除して再度ビルド.
--------------------Configuration: phpup_mb - Win32 Debug--------------------
Linking...
LINK : LNK6004: c:\Temp\HTM\phpup\phpup_mb\Debug.060/phpup_mb.exe not found or not built by the last incremental link; performing full link
ComPrj01.obj : fatal error LNK1143: invalid or corrupt file: no symbol for comdat section 0xffff8000
Error executing link.exe.
phpup_mb.exe - 1 error(s), 0 warning(s)
obj のサイズを見ると,20 MB 位になっている.
それで思い出したのが,前にも同じ様な現象が…
LNK1143 : ファイルが無効であるか…
ソースを分割して対応.
MFC ウィンドウ位置の保存
以前から,実装しようとしていつも見返してしまうので…
単純にウィンドウ位置を保存するタイミングは OnDestroy が良さそう.
他には,ダイアログで「OK」を押された場合( OnOK )などもある.
ウィンドウ位置を保存するコードは次の様な感じ.
if (!wnd->IsIconic()) {
CRect wRect ;
wnd->GetWindowRect(&wRect) ;
// SaveRect(SecDialog,entry,wRect) ;
}
起動時は
CRect rect ; rect.SetRectEmpty() ;
// rect = GetRect(SecDialog,entry,rect) ;
if (!rect.IsRectNull()) {
// ::SystemParametersInfo(SPI_GETWORKAREA,0,&workArea,0) ;
// 範囲の補正
wnd->MoveWindow(rect) ;
}
CMainFrame を持つ AP では CMainFrame::OnCreate で,ダイアログの場合は OnInitDialog で MoveWindow する.
CComboBox::SetItemHeight (-1,…)
高 DPI 対応で修正していて,コンボボックス(特に,オーナードロー?)の高さが他に比べて不自然.
ドキュメントを見ると,CB_SETITEMHEIGHT と思うが,指定方法がよくわからない.
「コンボボックス 高さ 変更」で 検索する と「できない」と記述されている所もある.
CB_SETITEMHEIGHT で検索していると,-1 を指定しているものがある.
さらに,CB_GETITEMHEIGHT のドキュメントを見ると,次の様にある.
選択フィールドの高さを取得するには、このパラメーターは -1 である必要があります
どうも CB_SETITEMHEIGHT の表現がうまくないものと思う.
次の様なコードで対応.
{
CRect rect ;
m_CtrlStrText.GetClientRect(&rect) ;
FontFace.SendMessage(CB_SETITEMHEIGHT,-1,rect.Height()) ;
FontFace.SendMessage(CB_SETITEMHEIGHT, 0,rect.Height()*15/10) ;
}
2023/05/16
ドロップダウンの幅がうまくなかったが,共通コードを見るといろいろ考慮しなければならない部分が多い.
そのため,次の様なコードで対応.
{
new_w = now_w ;
// new_w = now_w * 15 / 10 ;
new_w = int(new_w * ::GetDPI_scale(this->GetSafeHwnd())) ; // new_w*(::GetDpiForWindow()/96.)
FontFace.SendMessage(CB_SETDROPPEDWIDTH,new_w) ;
}
間違っているかもしれないが,CB_SETITEMHEIGHT を簡単にテストしたことのまとめ.
通常のコンボボックスの場合 | -1 で,全ての項目の高さを設定できる |
オーナードロー 固定 | -1 で,エディットボックス部分の高さを指定 0 で,ドロップ部分の項目の高さを指定 |
オーナードロー 可変 | -1 で,エディットボックス部分の高さを指定 0 以上で,ドロップ部分のそれぞれの高さを指定 |
VirtualBox PXE-E06
Win11 上の仮想マシン Win10 の Windows Update での再起動で,
PXE-E06: Option ROM requires DDIM support.
検索してみた が,あまりいい情報に引っ掛からない.
Windows Update での再起動だったので心配だったが,仮想マシンを一度 OFF して,再起動.
特に何もなかったかの様に起動した.
何だったのだろう.
2024/04/05
その後頻繁にこの現象が発生する.VirtualBox と Windows との相性か?
高 DPI VC 「高い DPI 認識」
引き続きいろいろとやっているが…
異なる DPI での対応は簡単ではなさそう.
VC のプロパティで「モニターごと高い DPI 認識」としてビルドしていたが,モニタ間を移動するとうまくない.
ちゃんと対応すれば良いのだろうが,簡単ではない.
そのため exe のプロパティで「システム(拡張)」で良いと思っていたが,幾つかのバグ?(未対応)がある.
VC のプロパティで「高い DPI 認識」にしてビルドしたものの方がうまく機能している様な気がする.
左から VC 10 ,14 ,10 ,14 としたもの.
タスクマネージャで見ると,VC 10 exe は「システム」として表示される.
左側のモニタの範囲は次の様になる.
-1920 130 0 1210 100% 1920 1080 「非対応」や「モニタごと」の場合
-3840 260 0 2420 200% 3840 2160 「システム」とした exe の場合
右側は ( 0 , 0 ) – ( 3840 , 2160 ) .
GDI スケーリングの動作として,次の記述があった.
アプリケーションが 100% (96 DPI) の倍数ではないディスプレイで実行されている場合、ベクター グラフィックスとテキストは、ディスプレイの倍率より 100% 高い最初の整数倍にレンダリングされます。たとえば、アプリケーションが 225% の縮尺のディスプレイ上にある場合、ベクター グラフィックスとビットマップは 300% でレンダリングされます。その後、DWM はレンダリングされたコンテンツを 225% のスケールに縮小します。この場合、スケールダウンによりアプリケーションのあいまいさが目立ちますが、100%レンダリングされたコンテンツを単純にスケールアップするよりも見栄えが良くなります。
Improving the high-DPI experience in GDI based Desktop Apps
How to build high DPI aware native Windows desktop applications
2023/05/12
「システム(拡張)」で幾つか変な動作があったが,「高い DPI 認識」でビルドしたものであれば良さそう.
CWinApp::m_pszRegistryKey
VC で MFC プロジェクトを作成すると,CXxxApp::InitInstance が次の様になる.
SetRegistryKey(_T(“アプリケーション ウィザードで生成されたローカル アプリケーション”));
ドキュメントにある様に,会社名などを指定する.
The registry key is usually the name of a company.
あまりやってはいけないことだろうと思うが,ドキュメントを見ていると,その設定した値 CWinApp::m_pszRegistryKey を直接変更できる.
そこのサンプルコードが… 何年も前から変わっていない.
CWinApp::SetRegistryKey の動作は,新しいキーに変更して m_pszPforileName も変更している.
MFC を使用するコンソール AP での SetRegistryKey の使用は次の所.
https://dev.mish.work/wordpress/2021/07/21/console-ap-setregistrykey/
[MyDNS.JP] IPアドレスの通知が …
OpenMP Fatal User Error 1002
OpenMP が有効な時でも動作する様にテストしていると…
Fatal User Error 1002: A ‘#pragma omp critical’ is illegally nested in one of the same name
元々あった次のコードに #pragma omp critical としたことによるもの.
tstring Get_Self_Original (void)
{
static bool Yet = true ;
static tstring Self_original ;
if (Yet) {
tstring self_name = ::Get_module_name() ;
Self_original = Get_OriginalFilename(self_name.c_str()) ;
if (Self_original.empty()) {
Self_original = ::Path_GetName(self_name) ;
}
Yet = false ;
}
return Self_original ;
}
次の様に並列処理可能にすることで動作する様にはなるが …
tstring Get_Self_Original (void)
{
#ifdef _OPENMP
// #pragma omp critical (_Get_Self_Original_)
#endif
{
#ifdef _OPENMP
bool Yet = true ;
tstring Self_original ;
#else
static bool Yet = true ;
static tstring Self_original ;
#endif
if (Yet) {
tstring self_name = ::Get_module_name() ;
Self_original = Get_OriginalFilename(self_name.c_str()) ;
if (Self_original.empty()) {
Self_original = ::Path_GetName(self_name) ;
}
Yet = false ;
}
return Self_original ;
}
}
以前にも同じようなことをやっていた.
https://dev.mish.work/wordpress/2010/03/31/openmp-error-1002/
2023/04/27
この関数は exe の起動直後などに一度呼ばれることを意図しているので,critical をもっと局所的に.
tstring Get_Self_Original (void)
{
static bool Yet = true ;
static tstring Self_original ;
if (Yet) {
#ifdef _OPENMP
#pragma omp critical (_Get_Self_Original_)
#endif
{
tstring self_name = ::Get_module_name() ;
Self_original = Get_OriginalFilename(self_name.c_str()) ;
if (Self_original.empty()) {
Self_original = ::Path_GetName(self_name) ;
}
Yet = false ;
}
}
return Self_original ;
}
C++ メンバ関数テンプレート
.ini に対してのアクセスは関数として用意した が,今度はレジストリ.
クラスとして実装して,基本的な動作は何とかできた.
さらに .ini と同様に,文字列としてアクセスする部分を呼出す関数をテンプレートに…
と思って書き始めたが,今まで使ってなかったのか書き方がわからない.
検索すると,次の所があり参考にさせてもらった.
メンバ関数テンプレート | Programming Place Plus C++編【言語解説】 第33章
メンバー関数テンプレート
特に通常の関数テンプレートと書き方は変わらない.
template <typename T> T get ( LPCTSTR ent,const T& def) {
tstring dst = ::To_tstring(def) ;
tstring str = this->get(ent,dst.c_str()) ;
T val ;
::string_to(str.c_str(),&val) ;
return val ;
}
template <typename T> bool set ( LPCTSTR ent,const T& val) {
tstring str = ::To_tstring(val) ;
return this->set(ent,str.c_str()) ;
}