├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ └── msbuild.yml ├── .gitignore ├── LICENSE.txt ├── README.txt ├── cditest ├── cditest.c ├── cditest.vcxproj ├── cditest.vcxproj.filters ├── disklib.c ├── disklib.h └── packages.config ├── libcdi.sln └── libcdi ├── AtaSmart.cpp ├── AtaSmart.h ├── DnpService.h ├── JMicronUsbRaidDef.h ├── JMicronUsbRaidInit.h ├── NVMeInterpreter.cpp ├── NVMeInterpreter.h ├── Priscilla ├── OsInfoFx.cpp ├── OsInfoFx.h ├── UtilityFx.cpp ├── UtilityFx.h ├── md5.cpp └── md5.h ├── Resource.rc ├── SPTIUtil.h ├── SlotSpeedGetter.cpp ├── SlotSpeedGetter.h ├── Source.def ├── StorageQuery.h ├── libcdi.cpp ├── libcdi.h ├── libcdi.vcxproj ├── libcdi.vcxproj.filters ├── packages.config ├── resource.h ├── smartids.h ├── stdafx.h └── version.h /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "github-actions" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | -------------------------------------------------------------------------------- /.github/workflows/msbuild.yml: -------------------------------------------------------------------------------- 1 | name: MSBuild 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - "main" 8 | 9 | env: 10 | # Path to the solution file relative to the root of the project. 11 | SOLUTION_FILE_PATH: . 12 | 13 | jobs: 14 | build: 15 | runs-on: windows-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | 20 | - name: Add MSBuild to PATH 21 | uses: microsoft/setup-msbuild@v2 22 | 23 | - name: Restore NuGet packages 24 | working-directory: ${{env.GITHUB_WORKSPACE}} 25 | run: nuget restore ${{env.SOLUTION_FILE_PATH}} 26 | 27 | - name: Build 28 | working-directory: ${{env.GITHUB_WORKSPACE}} 29 | # Add additional options to the MSBuild command line here (like platform or verbosity level). 30 | # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference 31 | run: | 32 | msbuild /m /p:Configuration=Release /p:platform=x64 ${{env.SOLUTION_FILE_PATH}} 33 | msbuild /m /p:Configuration=Release /p:platform=x86 ${{env.SOLUTION_FILE_PATH}} 34 | msbuild /m /p:Configuration=Release /p:platform=arm64 ${{env.SOLUTION_FILE_PATH}} 35 | md build 36 | md build\x64 37 | move x64\Release\libcdi.dll build\x64\libcdi.dll 38 | move x64\Release\cditest.exe build\x64\cditest.exe 39 | md build\x86 40 | move Win32\Release\libcdi.dll build\x86\libcdi.dll 41 | move Win32\Release\cditest.exe build\x86\cditest.exe 42 | md build\ARM64 43 | move ARM64\Release\libcdi.dll build\ARM64\libcdi.dll 44 | move ARM64\Release\cditest.exe build\ARM64\cditest.exe 45 | copy libcdi\libcdi.h build\libcdi.h 46 | copy LICENSE.txt build\LICENSE 47 | copy README.txt build\README.txt 48 | 49 | - name: Create ZIP 50 | uses: thedoctor0/zip-release@master 51 | with: 52 | type: 'zip' 53 | filename: 'libcdi.zip' 54 | directory: 'build' 55 | 56 | - name: Delete old release 57 | continue-on-error: true 58 | working-directory: ${{env.GITHUB_WORKSPACE}} 59 | run: | 60 | gh release delete latest --cleanup-tag --yes 61 | env: 62 | GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 63 | 64 | - name: Release 65 | working-directory: ${{env.GITHUB_WORKSPACE}} 66 | run: | 67 | gh release create latest build\libcdi.zip --latest -t "Development Build" 68 | env: 69 | GH_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 70 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Ll]og/ 33 | [Ll]ogs/ 34 | 35 | # Visual Studio 2015/2017 cache/options directory 36 | .vs/ 37 | # Uncomment if you have tasks that create the project's static files in wwwroot 38 | #wwwroot/ 39 | 40 | # Visual Studio 2017 auto generated files 41 | Generated\ Files/ 42 | 43 | # MSTest test Results 44 | [Tt]est[Rr]esult*/ 45 | [Bb]uild[Ll]og.* 46 | 47 | # NUnit 48 | *.VisualState.xml 49 | TestResult.xml 50 | nunit-*.xml 51 | 52 | # Build Results of an ATL Project 53 | [Dd]ebugPS/ 54 | [Rr]eleasePS/ 55 | dlldata.c 56 | 57 | # Benchmark Results 58 | BenchmarkDotNet.Artifacts/ 59 | 60 | # .NET Core 61 | project.lock.json 62 | project.fragment.lock.json 63 | artifacts/ 64 | 65 | # ASP.NET Scaffolding 66 | ScaffoldingReadMe.txt 67 | 68 | # StyleCop 69 | StyleCopReport.xml 70 | 71 | # Files built by Visual Studio 72 | *_i.c 73 | *_p.c 74 | *_h.h 75 | *.ilk 76 | *.meta 77 | *.obj 78 | *.iobj 79 | *.pch 80 | *.pdb 81 | *.ipdb 82 | *.pgc 83 | *.pgd 84 | *.rsp 85 | *.sbr 86 | *.tlb 87 | *.tli 88 | *.tlh 89 | *.tmp 90 | *.tmp_proj 91 | *_wpftmp.csproj 92 | *.log 93 | *.tlog 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Nuget personal access tokens and Credentials 210 | # nuget.config 211 | 212 | # Microsoft Azure Build Output 213 | csx/ 214 | *.build.csdef 215 | 216 | # Microsoft Azure Emulator 217 | ecf/ 218 | rcf/ 219 | 220 | # Windows Store app package directories and files 221 | AppPackages/ 222 | BundleArtifacts/ 223 | Package.StoreAssociation.xml 224 | _pkginfo.txt 225 | *.appx 226 | *.appxbundle 227 | *.appxupload 228 | 229 | # Visual Studio cache files 230 | # files ending in .cache can be ignored 231 | *.[Cc]ache 232 | # but keep track of directories ending in .cache 233 | !?*.[Cc]ache/ 234 | 235 | # Others 236 | ClientBin/ 237 | ~$* 238 | *~ 239 | *.dbmdl 240 | *.dbproj.schemaview 241 | *.jfm 242 | *.pfx 243 | *.publishsettings 244 | orleans.codegen.cs 245 | 246 | # Including strong name files can present a security risk 247 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 248 | #*.snk 249 | 250 | # Since there are multiple workflows, uncomment next line to ignore bower_components 251 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 252 | #bower_components/ 253 | 254 | # RIA/Silverlight projects 255 | Generated_Code/ 256 | 257 | # Backup & report files from converting an old project file 258 | # to a newer Visual Studio version. Backup files are not needed, 259 | # because we have git ;-) 260 | _UpgradeReport_Files/ 261 | Backup*/ 262 | UpgradeLog*.XML 263 | UpgradeLog*.htm 264 | ServiceFabricBackup/ 265 | *.rptproj.bak 266 | 267 | # SQL Server files 268 | *.mdf 269 | *.ldf 270 | *.ndf 271 | 272 | # Business Intelligence projects 273 | *.rdl.data 274 | *.bim.layout 275 | *.bim_*.settings 276 | *.rptproj.rsuser 277 | *- [Bb]ackup.rdl 278 | *- [Bb]ackup ([0-9]).rdl 279 | *- [Bb]ackup ([0-9][0-9]).rdl 280 | 281 | # Microsoft Fakes 282 | FakesAssemblies/ 283 | 284 | # GhostDoc plugin setting file 285 | *.GhostDoc.xml 286 | 287 | # Node.js Tools for Visual Studio 288 | .ntvs_analysis.dat 289 | node_modules/ 290 | 291 | # Visual Studio 6 build log 292 | *.plg 293 | 294 | # Visual Studio 6 workspace options file 295 | *.opt 296 | 297 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 298 | *.vbw 299 | 300 | # Visual Studio LightSwitch build output 301 | **/*.HTMLClient/GeneratedArtifacts 302 | **/*.DesktopClient/GeneratedArtifacts 303 | **/*.DesktopClient/ModelManifest.xml 304 | **/*.Server/GeneratedArtifacts 305 | **/*.Server/ModelManifest.xml 306 | _Pvt_Extensions 307 | 308 | # Paket dependency manager 309 | .paket/paket.exe 310 | paket-files/ 311 | 312 | # FAKE - F# Make 313 | .fake/ 314 | 315 | # CodeRush personal settings 316 | .cr/personal 317 | 318 | # Python Tools for Visual Studio (PTVS) 319 | __pycache__/ 320 | *.pyc 321 | 322 | # Cake - Uncomment if you are using it 323 | # tools/** 324 | # !tools/packages.config 325 | 326 | # Tabs Studio 327 | *.tss 328 | 329 | # Telerik's JustMock configuration file 330 | *.jmconfig 331 | 332 | # BizTalk build output 333 | *.btp.cs 334 | *.btm.cs 335 | *.odx.cs 336 | *.xsd.cs 337 | 338 | # OpenCover UI analysis results 339 | OpenCover/ 340 | 341 | # Azure Stream Analytics local run output 342 | ASALocalRun/ 343 | 344 | # MSBuild Binary and Structured Log 345 | *.binlog 346 | 347 | # NVidia Nsight GPU debugger configuration file 348 | *.nvuser 349 | 350 | # MFractors (Xamarin productivity tool) working folder 351 | .mfractor/ 352 | 353 | # Local History for Visual Studio 354 | .localhistory/ 355 | 356 | # BeatPulse healthcheck temp database 357 | healthchecksdb 358 | 359 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 360 | MigrationBackup/ 361 | 362 | # Ionide (cross platform F# VS Code tools) working folder 363 | .ionide/ 364 | 365 | # Fody - auto-generated XML schema 366 | FodyWeavers.xsd 367 | 368 | # VS Code files for those working on multiple tools 369 | .vscode/* 370 | !.vscode/settings.json 371 | !.vscode/tasks.json 372 | !.vscode/launch.json 373 | !.vscode/extensions.json 374 | *.code-workspace 375 | 376 | # Local History for Visual Studio Code 377 | .history/ 378 | 379 | # Windows Installer files from build outputs 380 | *.cab 381 | *.msi 382 | *.msix 383 | *.msm 384 | *.msp 385 | 386 | # JetBrains Rider 387 | .idea/ 388 | *.sln.iml -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2008-2023 hiyohiyo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | CrystalDiskInfo 动态链接库 2 | MIT license 3 | https://github.com/hiyohiyo/CrystalDiskInfo 4 | https://github.com/iTXTech/CrystalDiskInfoEmbedded 5 | 导出函数: 6 | CONST CHAR* WINAPI cdi_get_version(VOID) 7 | 获取 CDI 版本 8 | 参数: 9 | 返回值: 10 | 返回 CDI 版本号,如 "9.0.0"。 11 | CDI_SMART* WINAPI cdi_create_smart(VOID) 12 | 创建 SMART 数据。加载 DLL 后,应首先执行 CoInitializeEx ,再调用此函数。 13 | 参数: 14 | 返回值: 15 | 返回 CDI_SMART 结构体指针供其他函数使用。 16 | 使用完毕后,请调用 cdi_destroy_smart 释放内存。 17 | VOID WINAPI cdi_destroy_smart(CDI_SMART* ptr); 18 | 释放 SMART 数据。 19 | 参数: 20 | ptr 由 cdi_create_smart 获取的 CDI_SMART 结构体指针。 21 | 返回值: 22 | VOID WINAPI cdi_init_smart(CDI_SMART* ptr, UINT64 flags); 23 | 初始化 SMART 数据。在 cdi_create_smart 之后执行。遍历所有磁盘,收集 SMART 信息。 24 | 参数: 25 | ptr 由 cdi_create_smart 获取的 CDI_SMART 结构体指针。 26 | flags 设置磁盘处理的各种选项,见下方 磁盘处理选项 部分。建议值为 0x01FBFF81。 27 | 返回值: 28 | DWORD WINAPI cdi_update_smart(CDI_SMART* ptr, INT index); 29 | 更新硬盘的 SMART 信息。 30 | 参数: 31 | ptr 由 cdi_create_smart 获取的 CDI_SMART 结构体指针。 32 | index 硬盘序号,从 0 开始,最大值为 cdi_get_disk_count 的返回值减 1。 33 | 返回值: 34 | 若磁盘的 SMART 信息无改动,则返回 0。 35 | INT WINAPI cdi_get_disk_count(CDI_SMART* ptr); 36 | 获取磁盘计数。 37 | 参数: 38 | ptr 由 cdi_create_smart 获取的 CDI_SMART 结构体指针。 39 | 返回值: 40 | 磁盘计数。 41 | BOOL WINAPI cdi_get_bool(CDI_SMART* ptr, INT index, enum CDI_ATA_BOOL attr); 42 | 获取 BOOL 类型的磁盘属性。 43 | 参数: 44 | ptr 由 cdi_create_smart 获取的 CDI_SMART 结构体指针。 45 | index 硬盘序号,从 0 开始,最大值为 cdi_get_disk_count 的返回值减 1。 46 | attr 磁盘属性,见下方 磁盘属性 (BOOL) 部分。 47 | 返回值: 48 | BOOL 类型的对应磁盘属性。 49 | INT WINAPI cdi_get_int(CDI_SMART* ptr, INT index, enum CDI_ATA_INT attr); 50 | 获取 INT 类型的磁盘属性。 51 | 参数: 52 | ptr 由 cdi_create_smart 获取的 CDI_SMART 结构体指针。 53 | index 硬盘序号,从 0 开始,最大值为 cdi_get_disk_count 的返回值减 1。 54 | attr 磁盘属性,见下方 磁盘属性 (INT) 部分。 55 | 返回值: 56 | INT 类型的对应磁盘属性。若返回值为负数,则表明该属性无效。 57 | DWORD WINAPI cdi_get_dword(CDI_SMART* ptr, INT index, enum CDI_ATA_DWORD attr); 58 | 获取 DWORD 类型的磁盘属性。 59 | 参数: 60 | ptr 由 cdi_create_smart 获取的 CDI_SMART 结构体指针。 61 | index 硬盘序号,从 0 开始,最大值为 cdi_get_disk_count 的返回值减 1。 62 | attr 磁盘属性,见下方 磁盘属性 (DWORD) 部分。 63 | 返回值: 64 | DWORD 类型的对应磁盘属性。 65 | WCHAR* WINAPI cdi_get_string(CDI_SMART* ptr, INT index, enum CDI_ATA_STRING attr); 66 | 获取字符串类型的磁盘属性。 67 | 参数: 68 | ptr 由 cdi_create_smart 获取的 CDI_SMART 结构体指针。 69 | index 硬盘序号,从 0 开始,最大值为 cdi_get_disk_count 的返回值减 1。 70 | attr 磁盘属性,见下方 磁盘属性 (WCHAR*) 部分。 71 | 返回值: 72 | 字符串类型的对应磁盘属性。使用 cdi_free_string 释放内存。 73 | VOID WINAPI cdi_free_string(WCHAR* ptr); 74 | 释放字符串的内存。 75 | 参数: 76 | ptr 字符串指针。 77 | 返回值: 78 | WCHAR* WINAPI cdi_get_smart_format(CDI_SMART* ptr, INT index); 79 | 获取 SMART 数据格式。 80 | 参数: 81 | ptr 由 cdi_create_smart 获取的 CDI_SMART 结构体指针。 82 | index 硬盘序号,从 0 开始,最大值为 cdi_get_disk_count 的返回值减 1。 83 | 返回值: 84 | SMART 数据的格式。 85 | 可能的返回值为 RawValues(7),RawValues(8),Cur RawValues(8),Cur Wor --- RawValues(6),Cur Wor Thr RawValues(6),Cur Wor --- RawValues(7), Cur Wor Thr RawValues(7)。 86 | 使用 cdi_free_string 释放内存。 87 | BYTE WINAPI cdi_get_smart_id(CDI_SMART* ptr, INT index, INT attr); 88 | 获取 SMART 属性的 ID。 89 | 参数: 90 | ptr 由 cdi_create_smart 获取的 CDI_SMART 结构体指针。 91 | index 硬盘序号,从 0 开始,最大值为 cdi_get_disk_count 的返回值减 1。 92 | attr SMART 属性序号,从 0 开始,最大值为 CDI_DWORD_ATTR_COUNT 属性的值减 1。 93 | 返回值: 94 | SMART 属性的 ID。 95 | WCHAR* WINAPI cdi_get_smart_value(CDI_SMART* ptr, INT index, INT attr, BOOL hex); 96 | 获取 SMART 属性的数据。 97 | 参数: 98 | ptr 由 cdi_create_smart 获取的 CDI_SMART 结构体指针。 99 | index 硬盘序号,从 0 开始,最大值为 cdi_get_disk_count 的返回值减 1。 100 | attr SMART 属性序号,从 0 开始,最大值为 CDI_DWORD_ATTR_COUNT 属性的值减 1。 101 | hex 是否以十六进制格式显示原始值。 102 | 返回值: 103 | SMART 属性的数据。使用 cdi_free_string 释放内存。 104 | INT WINAPI cdi_get_smart_status(CDI_SMART* ptr, INT index, INT attr); 105 | 获取 SMART 属性的状态。 106 | 参数: 107 | ptr 由 cdi_create_smart 获取的 CDI_SMART 结构体指针。 108 | index 硬盘序号,从 0 开始,最大值为 cdi_get_disk_count 的返回值减 1。 109 | attr SMART 属性序号,从 0 开始,最大值为 CDI_DWORD_ATTR_COUNT 属性的值减 1。 110 | 返回值: 111 | SMART 属性的状态。请参考 磁盘健康状态 部分。 112 | WCHAR* WINAPI *cdi_get_smart_name(CDI_SMART* ptr, INT index, BYTE id); 113 | 获取 SMART 属性的名称。 114 | 参数: 115 | ptr 由 cdi_create_smart 获取的 CDI_SMART 结构体指针。 116 | index 硬盘序号,从 0 开始,最大值为 cdi_get_disk_count 的返回值减 1。 117 | id SMART 属性的 ID,可由 cdi_get_smart_id 获取。 118 | 返回值: 119 | SMART 属性的名称。使用 cdi_free_string 释放内存。 120 | 121 | 磁盘处理选项 122 | #define CDI_FLAG_USE_WMI (1ULL << 0) // TRUE 123 | #define CDI_FLAG_ADVANCED_SEARCH (1ULL << 1) // FALSE 124 | #define CDI_FLAG_WORKAROUND_HD204UI (1ULL << 2) // FALSE 125 | #define CDI_FLAG_WORKAROUND_ADATA (1ULL << 3) // FALSE 126 | #define CDI_FLAG_HIDE_NO_SMART (1ULL << 4) // FALSE 127 | #define CDI_FLAG_SORT_DRIVE_LETTER (1ULL << 5) // FALSE 128 | #define CDI_FLAG_NO_WAKEUP (1ULL << 6) // FALSE 129 | #define CDI_FLAG_ATA_PASS_THROUGH (1ULL << 7) // TRUE 130 | #define CDI_FLAG_ENABLE_NVIDIA (1ULL << 8) // TRUE 131 | #define CDI_FLAG_ENABLE_MARVELL (1ULL << 9) // TRUE 132 | #define CDI_FLAG_ENABLE_USB_SAT (1ULL << 10) // TRUE 133 | #define CDI_FLAG_ENABLE_USB_SUNPLUS (1ULL << 11) // TRUE 134 | #define CDI_FLAG_ENABLE_USB_IODATA (1ULL << 12) // TRUE 135 | #define CDI_FLAG_ENABLE_USB_LOGITEC (1ULL << 13) // TRUE 136 | #define CDI_FLAG_ENABLE_USB_PROLIFIC (1ULL << 14) // TRUE 137 | #define CDI_FLAG_ENABLE_USB_JMICRON (1ULL << 15) // TRUE 138 | #define CDI_FLAG_ENABLE_USB_CYPRESS (1ULL << 16) // TRUE 139 | #define CDI_FLAG_ENABLE_USB_MEMORY (1ULL << 17) // TRUE 140 | 141 | #define CDI_FLAG_ENABLE_NVME_JMICRON (1ULL << 19) // TRUE 142 | #define CDI_FLAG_ENABLE_NVME_ASMEDIA (1ULL << 20) // TRUE 143 | #define CDI_FLAG_ENABLE_NVME_REALTEK (1ULL << 21) // TRUE 144 | #define CDI_FLAG_ENABLE_MEGA_RAID (1ULL << 22) // TRUE 145 | #define CDI_FLAG_ENABLE_INTEL_VROC (1ULL << 23) // TRUE 146 | #define CDI_FLAG_ENABLE_ASM1352R (1ULL << 24) // TRUE 147 | #define CDI_FLAG_ENABLE_AMD_RC2 (1ULL << 25) // FALSE 148 | #define CDI_FLAG_ENABLE_REALTEK_9220DP (1ULL << 26) // FALSE 149 | 150 | #define CDI_FLAG_HIDE_RAID_VOLUME (1ULL << 27) // TRUE 151 | 152 | 磁盘属性 (BOOL): 153 | enum CDI_ATA_BOOL 154 | { 155 | CDI_BOOL_SSD = 0, // 是否为 SSD 156 | CDI_BOOL_SSD_NVME, // 是否为 NVMe SSD (>=Win10) 157 | CDI_BOOL_SMART, // 是否支持 SMART 158 | CDI_BOOL_LBA48, 159 | CDI_BOOL_AAM, 160 | CDI_BOOL_APM, 161 | CDI_BOOL_NCQ, 162 | CDI_BOOL_NV_CACHE, 163 | CDI_BOOL_DEVSLP, 164 | CDI_BOOL_STREAMING, 165 | CDI_BOOL_GPL, 166 | CDI_BOOL_TRIM, 167 | CDI_BOOL_VOLATILE_WRITE_CACHE, 168 | CDI_BOOL_SMART_ENABLED, 169 | CDI_BOOL_AAM_ENABLED, 170 | CDI_BOOL_APM_ENABLED, 171 | }; 172 | 173 | 磁盘属性 (INT): 174 | enum CDI_ATA_INT 175 | { 176 | CDI_INT_DISK_ID = 0, // 磁盘 ID,即 \\.\PhysicalDriveX 177 | CDI_INT_DISK_STATUS, // 磁盘健康状态,请参考 磁盘健康状态 部分 178 | CDI_INT_SCSI_PORT, 179 | CDI_INT_SCSI_TARGET_ID, 180 | CDI_INT_SCSI_BUS, 181 | CDI_INT_POWER_ON_HOURS, // 通电时间 (小时) 182 | CDI_INT_TEMPERATURE, // 温度 (C) 183 | CDI_INT_TEMPERATURE_ALARM, // 警告温度 (C) 184 | CDI_INT_HOST_WRITES, // 主机总计写入 (GB) 185 | CDI_INT_HOST_READS, // 主机总计读取 (GB) 186 | CDI_INT_NAND_WRITES, // NAND 写入量 (GB) 187 | CDI_INT_GB_ERASED, // 擦取量 (GB) 188 | CDI_INT_WEAR_LEVELING_COUNT, 189 | CDI_INT_LIFE, // 健康度 (0% - 100%) 190 | CDI_INT_MAX_ATTRIBUTE, 191 | }; 192 | 193 | 磁盘属性 (DWORD): 194 | enum CDI_ATA_DWORD 195 | { 196 | CDI_DWORD_DISK_SIZE = 0, // 磁盘大小 (MB) 197 | CDI_DWORD_LOGICAL_SECTOR_SIZE, // 逻辑扇区大小 198 | CDI_DWORD_PHYSICAL_SECTOR_SIZE, // 物理扇区大小 199 | CDI_DWORD_BUFFER_SIZE, // 缓存大小 (B) 200 | CDI_DWORD_ATTR_COUNT, // SMART 属性总数 201 | CDI_DWORD_POWER_ON_COUNT, // 通电次数 202 | CDI_DWORD_ROTATION_RATE, // 转速 (RPM) 203 | CDI_DWORD_DRIVE_LETTER, 204 | CDI_DWORD_DISK_VENDOR_ID, 205 | }; 206 | 207 | 磁盘属性 (WCHAR*): 208 | enum CDI_ATA_STRING 209 | { 210 | CDI_STRING_SN = 0, // 序列号 211 | CDI_STRING_FIRMWARE, // 固件 212 | CDI_STRING_MODEL, // 型号 213 | CDI_STRING_DRIVE_MAP, // 盘符列表 214 | CDI_STRING_TRANSFER_MODE_MAX, // 最大传输模式 215 | CDI_STRING_TRANSFER_MODE_CUR, // 当前传输模式 216 | CDI_STRING_INTERFACE, // 接口 (如:NVM Express) 217 | CDI_STRING_VERSION_MAJOR, 218 | CDI_STRING_VERSION_MINOR, 219 | CDI_STRING_PNP_ID, 220 | CDI_STRING_SMART_KEY, 221 | }; 222 | 223 | 磁盘健康状态: 224 | enum CDI_DISK_STATUS 225 | { 226 | CDI_DISK_STATUS_UNKNOWN = 0, // 未知 227 | CDI_DISK_STATUS_GOOD, // 良好 228 | CDI_DISK_STATUS_CAUTION, // 警告 229 | CDI_DISK_STATUS_BAD // 损坏 230 | }; 231 | -------------------------------------------------------------------------------- /cditest/cditest.c: -------------------------------------------------------------------------------- 1 |  2 | #define VC_EXTRALEAN 3 | #include 4 | #include 5 | 6 | #include "../libcdi/libcdi.h" 7 | #include "disklib.h" 8 | #pragma comment(lib, "libcdi.lib") 9 | #pragma comment(lib, "setupapi.lib") 10 | 11 | static INT 12 | GetSmartIndex(CDI_SMART* cdiSmart, DWORD dwId) 13 | { 14 | INT nCount = cdi_get_disk_count(cdiSmart); 15 | for (INT i = 0; i < nCount; i++) 16 | { 17 | if (cdi_get_int(cdiSmart, i, CDI_INT_DISK_ID) == (INT)dwId) 18 | return i; 19 | } 20 | return -1; 21 | } 22 | 23 | static VOID 24 | PrintSmartInfo(CDI_SMART* cdiSmart, PHY_DRIVE_INFO* pdInfo, INT nIndex) 25 | { 26 | INT d; 27 | DWORD n; 28 | WCHAR* str; 29 | BOOL ssd; 30 | BYTE id; 31 | 32 | if (nIndex < 0) 33 | { 34 | printf("\tSSD: %s\n", pdInfo->Ssd ? "Yes" : "No"); 35 | printf("\tSerial: %s\n", pdInfo->SerialNumber); 36 | return; 37 | } 38 | 39 | cdi_update_smart(cdiSmart, nIndex); 40 | 41 | ssd = cdi_get_bool(cdiSmart, nIndex, CDI_BOOL_SSD); 42 | printf("\tSSD: %s\n", ssd ? "Yes" : "No"); 43 | 44 | str = cdi_get_string(cdiSmart, nIndex, CDI_STRING_SN); 45 | printf("\tSerial: %s\n", Ucs2ToUtf8(str)); 46 | cdi_free_string(str); 47 | 48 | str = cdi_get_string(cdiSmart, nIndex, CDI_STRING_FIRMWARE); 49 | printf("\tFirmware: %s\n", Ucs2ToUtf8(str)); 50 | cdi_free_string(str); 51 | 52 | str = cdi_get_string(cdiSmart, nIndex, CDI_STRING_INTERFACE); 53 | printf("\tInterface: %s\n", Ucs2ToUtf8(str)); 54 | cdi_free_string(str); 55 | 56 | str = cdi_get_string(cdiSmart, nIndex, CDI_STRING_TRANSFER_MODE_CUR); 57 | printf("\tCurrent Transfer Mode: %s\n", Ucs2ToUtf8(str)); 58 | cdi_free_string(str); 59 | 60 | str = cdi_get_string(cdiSmart, nIndex, CDI_STRING_TRANSFER_MODE_MAX); 61 | printf("\tMax Transfer Mode: %s\n", Ucs2ToUtf8(str)); 62 | cdi_free_string(str); 63 | 64 | d = cdi_get_int(cdiSmart, nIndex, CDI_INT_LIFE); 65 | printf("\tHealth Status: %s", cdi_get_health_status(cdi_get_int(cdiSmart, nIndex, CDI_INT_DISK_STATUS))); 66 | if (d >= 0) 67 | printf(" (%d%%)\n", d); 68 | else 69 | printf("\n"); 70 | 71 | printf("\tTemperature: %d (C)\n", cdi_get_int(cdiSmart, nIndex, CDI_INT_TEMPERATURE)); 72 | 73 | str = cdi_get_smart_format(cdiSmart, nIndex); 74 | printf("\tID Status %-24s Name\n", Ucs2ToUtf8(str)); 75 | cdi_free_string(str); 76 | 77 | n = cdi_get_dword(cdiSmart, nIndex, CDI_DWORD_ATTR_COUNT); 78 | for (INT j = 0; j < (INT)n; j++) 79 | { 80 | id = cdi_get_smart_id(cdiSmart, nIndex, j); 81 | if (id == 0x00) 82 | continue; 83 | str = cdi_get_smart_value(cdiSmart, nIndex, j, FALSE); 84 | printf("\t%02X %7s %-24s", 85 | id, 86 | cdi_get_health_status(cdi_get_smart_status(cdiSmart, nIndex, j)), 87 | Ucs2ToUtf8(str)); 88 | printf(" %s\n", Ucs2ToUtf8(cdi_get_smart_name(cdiSmart, nIndex, id))); 89 | cdi_free_string(str); 90 | } 91 | } 92 | 93 | int main(int argc, char* argv[]) 94 | { 95 | DWORD dwCount; 96 | CDI_SMART* cdiSmart; 97 | PHY_DRIVE_INFO* pdInfo; 98 | 99 | (void)CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 100 | cdiSmart = cdi_create_smart(); 101 | 102 | printf("CDI v%s\n", cdi_get_version()); 103 | 104 | dwCount = GetDriveInfoList(FALSE, &pdInfo); 105 | printf("Disk Count: %lu\n", dwCount); 106 | 107 | cdi_init_smart(cdiSmart, CDI_FLAG_DEFAULT); 108 | 109 | for (DWORD i = 0; i < dwCount; i++) 110 | { 111 | printf("\\\\.\\PhysicalDrive%lu\n", pdInfo[i].Index); 112 | printf("\tHWID: %s\n", Ucs2ToUtf8(pdInfo[i].HwID)); 113 | printf("\tModel: %s\n", Ucs2ToUtf8(pdInfo[i].HwName)); 114 | printf("\tSize: %s\n", GetHumanSize(pdInfo[i].SizeInBytes, 1024)); 115 | printf("\tRemovable Media: %s\n", pdInfo[i].RemovableMedia ? "Yes" : "No"); 116 | printf("\tVendor Id: %s\n", pdInfo[i].VendorId); 117 | printf("\tProduct Id: %s\n", pdInfo[i].ProductId); 118 | printf("\tProduct Rev: %s\n", pdInfo[i].ProductRev); 119 | printf("\tBus Type: %s\n", GetBusTypeName(pdInfo[i].BusType)); 120 | 121 | printf("\tPartition Table: %s\n", GetPartMapName(pdInfo[i].PartMap)); 122 | switch(pdInfo[i].PartMap) 123 | { 124 | case PARTITION_STYLE_MBR: 125 | printf("\tMBR Signature: %02X %02X %02X %02X\n", 126 | pdInfo[i].MbrSignature[0], pdInfo[i].MbrSignature[1], 127 | pdInfo[i].MbrSignature[2], pdInfo[i].MbrSignature[3]); 128 | break; 129 | case PARTITION_STYLE_GPT: 130 | printf("\tGPT GUID: {%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n", 131 | pdInfo[i].GptGuid[0], pdInfo[i].GptGuid[1], pdInfo[i].GptGuid[2], pdInfo[i].GptGuid[3], 132 | pdInfo[i].GptGuid[4], pdInfo[i].GptGuid[5], pdInfo[i].GptGuid[6], pdInfo[i].GptGuid[7], 133 | pdInfo[i].GptGuid[8], pdInfo[i].GptGuid[9], pdInfo[i].GptGuid[10], pdInfo[i].GptGuid[11], 134 | pdInfo[i].GptGuid[12], pdInfo[i].GptGuid[13], pdInfo[i].GptGuid[14], pdInfo[i].GptGuid[15]); 135 | break; 136 | } 137 | 138 | PrintSmartInfo(cdiSmart, &pdInfo[i], GetSmartIndex(cdiSmart, pdInfo[i].Index)); 139 | for (DWORD j = 0; j < pdInfo[i].VolCount; j++) 140 | { 141 | DISK_VOL_INFO* p = &pdInfo[i].VolInfo[j]; 142 | printf("\t%s\n", Ucs2ToUtf8(p->VolPath)); 143 | 144 | printf("\t\tStarting LBA: %llu\n", p->StartLba); 145 | printf("\t\tPartition Number: %lu\n", p->PartNum); 146 | printf("\t\tPartition Type: %s\n", Ucs2ToUtf8(p->PartType)); 147 | printf("\t\tPartition ID: %s\n", Ucs2ToUtf8(p->PartId)); 148 | printf("\t\tBoot Indicator: %s\n", p->BootIndicator ? "Yes" : "No"); 149 | printf("\t\tPartition Flag: %s\n", Ucs2ToUtf8(p->PartFlag)); 150 | 151 | printf("\t\tLabel: %s\n", Ucs2ToUtf8(p->VolLabel)); 152 | printf("\t\tFS: %s\n", Ucs2ToUtf8(p->VolFs)); 153 | printf("\t\tFree Space: %s\n", GetHumanSize(p->VolFreeSpace.QuadPart, 1024)); 154 | printf("\t\tTotal Space: %s\n", GetHumanSize(p->VolTotalSpace.QuadPart, 1024)); 155 | printf("\t\tUsage: %.2f%%\n", p->VolUsage); 156 | printf("\t\tMount Points:\n"); 157 | for (WCHAR* q = p->VolNames; q[0] != L'\0'; q += wcslen(q) + 1) 158 | { 159 | printf("\t\t\t%s\n", Ucs2ToUtf8(q)); 160 | } 161 | } 162 | } 163 | 164 | cdi_destroy_smart(cdiSmart); 165 | DestoryDriveInfoList(pdInfo, dwCount); 166 | CoUninitialize(); 167 | return 0; 168 | } 169 | -------------------------------------------------------------------------------- /cditest/cditest.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Release 8 | ARM64 9 | 10 | 11 | Release 12 | Win32 13 | 14 | 15 | Release 16 | x64 17 | 18 | 19 | 20 | 16.0 21 | Win32Proj 22 | {20a977e8-8a04-4ac1-b050-d940e2e6ba13} 23 | cditest 24 | 10.0 25 | 26 | 27 | 28 | Application 29 | false 30 | v143 31 | true 32 | Unicode 33 | true 34 | true 35 | true 36 | 5.1.2600.0 37 | YY_Thunks_for_WinXP.obj 38 | 39 | 40 | Application 41 | false 42 | v143 43 | true 44 | Unicode 45 | true 46 | true 47 | true 48 | 5.1.2600.0 49 | YY_Thunks_for_WinXP.obj 50 | 51 | 52 | Application 53 | false 54 | v143 55 | true 56 | Unicode 57 | true 58 | true 59 | true 60 | 10.0.10240.0 61 | YY_Thunks_for_Win10.0.10240.obj 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | $(SolutionDir)$(Platform)\$(Configuration)\ 80 | $(Platform)\$(Configuration)\ 81 | 82 | 83 | $(Platform)\$(Configuration)\ 84 | 85 | 86 | $(Platform)\$(Configuration)\ 87 | 88 | 89 | 90 | Level3 91 | true 92 | true 93 | true 94 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 95 | true 96 | stdcpp20 97 | stdc17 98 | true 99 | MultiThreaded 100 | 101 | 102 | Console 103 | true 104 | true 105 | true 106 | RequireAdministrator 107 | 108 | 109 | 110 | 111 | Level3 112 | true 113 | true 114 | true 115 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 116 | true 117 | stdcpp20 118 | stdc17 119 | true 120 | MultiThreaded 121 | 122 | 123 | Console 124 | true 125 | true 126 | true 127 | RequireAdministrator 128 | 129 | 130 | 131 | 132 | Level3 133 | true 134 | true 135 | true 136 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 137 | true 138 | stdcpp20 139 | stdc17 140 | true 141 | MultiThreaded 142 | 143 | 144 | Console 145 | true 146 | true 147 | true 148 | RequireAdministrator 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | {f8c0b390-95be-4b12-ba9b-48b4774fdde4} 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 174 | 175 | 176 | 177 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /cditest/cditest.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 源文件 20 | 21 | 22 | 源文件 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 头文件 31 | 32 | 33 | -------------------------------------------------------------------------------- /cditest/disklib.c: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Unlicense 2 | 3 | #include "disklib.h" 4 | #include 5 | #include 6 | #include "../libcdi/libcdi.h" 7 | 8 | #define DISKLIB_BUFSZ 0x10000 9 | #define DISKLIB_BUFSZW (DISKLIB_BUFSZ / sizeof(WCHAR)) 10 | #define DISKLIB_BUFSZB (DISKLIB_BUFSZW * sizeof(WCHAR)) 11 | static union 12 | { 13 | CHAR c[DISKLIB_BUFSZ]; 14 | WCHAR w[DISKLIB_BUFSZW]; 15 | } mBuf; 16 | 17 | static VOID 18 | ErrorMsg(LPCSTR lpszText, INT nExitCode) 19 | { 20 | fprintf(stderr, "Error: %s\n", lpszText); 21 | exit(nExitCode); 22 | } 23 | 24 | static HANDLE 25 | GetDiskHandleById(BOOL bCdrom, BOOL bWrite, DWORD dwId) 26 | { 27 | WCHAR PhyPath[28]; // L"\\\\.\\PhysicalDrive4294967295" 28 | if (bCdrom) 29 | swprintf(PhyPath, 28, L"\\\\.\\CdRom%u", dwId); 30 | else 31 | swprintf(PhyPath, 28, L"\\\\.\\PhysicalDrive%u", dwId); 32 | return CreateFileW(PhyPath, bWrite ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_READ, 33 | FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0); 34 | } 35 | 36 | static LPCWSTR 37 | GuidToStr(BOOL bBracket, GUID* pGuid) 38 | { 39 | static WCHAR cchGuid[39] = { 0 }; 40 | swprintf(cchGuid, 39, L"%s%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X%s", 41 | bBracket ? L"{" : L"", 42 | pGuid->Data1, pGuid->Data2, pGuid->Data3, 43 | pGuid->Data4[0], pGuid->Data4[1], pGuid->Data4[2], pGuid->Data4[3], 44 | pGuid->Data4[4], pGuid->Data4[5], pGuid->Data4[6], pGuid->Data4[7], 45 | bBracket ? L"}" : L""); 46 | return cchGuid; 47 | } 48 | 49 | static LPCWSTR 50 | GetGptFlag(GUID* pGuid) 51 | { 52 | LPCWSTR lpszGuid = GuidToStr(FALSE, pGuid); 53 | if (_wcsicmp(lpszGuid, L"c12a7328-f81f-11d2-ba4b-00a0c93ec93b") == 0) 54 | return L"ESP"; 55 | else if (_wcsicmp(lpszGuid, L"e3c9e316-0b5c-4db8-817d-f92df00215ae") == 0) 56 | return L"MSR"; 57 | else if (_wcsicmp(lpszGuid, L"de94bba4-06d1-4d40-a16a-bfd50179d6ac") == 0) 58 | return L"WINRE"; 59 | else if (_wcsicmp(lpszGuid, L"21686148-6449-6e6f-744e-656564454649") == 0) 60 | return L"BIOS"; 61 | else if (_wcsicmp(lpszGuid, L"024dee41-33e7-11d3-9d69-0008c781f39f") == 0) 62 | return L"MBR"; 63 | return L"DATA"; 64 | } 65 | 66 | static LPCWSTR 67 | GetMbrFlag(LONGLONG llStartingOffset, PHY_DRIVE_INFO* pParent) 68 | { 69 | INT i; 70 | LONGLONG llLba = llStartingOffset >> 9; 71 | for (i = 0; i < 4; i++) 72 | { 73 | if (llLba == pParent->MbrLba[i]) 74 | return L"PRIMARY"; 75 | } 76 | return L"EXTENDED"; 77 | } 78 | 79 | static VOID 80 | FillPartitionInfo(DISK_VOL_INFO* pInfo, LPCWSTR lpszPath, PHY_DRIVE_INFO* pParent) 81 | { 82 | BOOL bRet; 83 | HANDLE hDevice = INVALID_HANDLE_VALUE; 84 | PARTITION_INFORMATION_EX partInfo = { 0 }; 85 | DWORD dwPartInfo = sizeof(PARTITION_INFORMATION_EX); 86 | hDevice = CreateFileW(lpszPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); 87 | if (!hDevice || hDevice == INVALID_HANDLE_VALUE) 88 | return; 89 | bRet = DeviceIoControl(hDevice, IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, &partInfo, dwPartInfo, &dwPartInfo, NULL); 90 | CloseHandle(hDevice); 91 | if (!bRet) 92 | return; 93 | if (partInfo.StartingOffset.QuadPart == 0) // CDROM 94 | return; 95 | pInfo->StartLba = partInfo.StartingOffset.QuadPart >> 9; 96 | pInfo->PartNum = partInfo.PartitionNumber; 97 | switch (partInfo.PartitionStyle) 98 | { 99 | case PARTITION_STYLE_MBR: 100 | swprintf(pInfo->PartType, DISK_PROP_STR_LEN, L"%02X", partInfo.Mbr.PartitionType); 101 | wcscpy_s(pInfo->PartId, DISK_PROP_STR_LEN, GuidToStr(TRUE, &partInfo.Mbr.PartitionId)); 102 | wcscpy_s(pInfo->PartFlag, DISK_PROP_STR_LEN, GetMbrFlag(partInfo.StartingOffset.QuadPart, pParent)); 103 | pInfo->BootIndicator = partInfo.Mbr.BootIndicator; 104 | break; 105 | case PARTITION_STYLE_GPT: 106 | wcscpy_s(pInfo->PartType, DISK_PROP_STR_LEN, GuidToStr(TRUE, &partInfo.Gpt.PartitionType)); 107 | wcscpy_s(pInfo->PartId, DISK_PROP_STR_LEN, GuidToStr(TRUE, &partInfo.Gpt.PartitionId)); 108 | wcscpy_s(pInfo->PartFlag, DISK_PROP_STR_LEN, GetGptFlag(&partInfo.Gpt.PartitionType)); 109 | pInfo->BootIndicator = (wcscmp(pInfo->PartFlag, L"ESP") == 0) ? TRUE : FALSE; 110 | break; 111 | } 112 | } 113 | 114 | static VOID 115 | FillVolumeInfo(DISK_VOL_INFO* pInfo, LPCWSTR lpszVolume, PHY_DRIVE_INFO* pParent) 116 | { 117 | DWORD dwSize = 0; 118 | 119 | swprintf(pInfo->VolPath, MAX_PATH, L"%s\\", lpszVolume); 120 | 121 | if (GetVolumeInformationW(pInfo->VolPath, pInfo->VolLabel, MAX_PATH, 122 | NULL, NULL, NULL, 123 | pInfo->VolFs, MAX_PATH)) 124 | { 125 | FillPartitionInfo(pInfo, lpszVolume, pParent); 126 | } 127 | GetDiskFreeSpaceExW(pInfo->VolPath, NULL, &pInfo->VolTotalSpace, &pInfo->VolFreeSpace); 128 | if (pInfo->VolTotalSpace.QuadPart != 0) 129 | pInfo->VolUsage = 100.0 - (pInfo->VolFreeSpace.QuadPart * 100.0) / pInfo->VolTotalSpace.QuadPart; 130 | GetVolumePathNamesForVolumeNameW(pInfo->VolPath, NULL, 0, &dwSize); 131 | if (GetLastError() == ERROR_MORE_DATA && dwSize) 132 | { 133 | pInfo->VolNames = calloc(dwSize, sizeof(WCHAR)); 134 | if (pInfo->VolNames) 135 | { 136 | if (!GetVolumePathNamesForVolumeNameW(pInfo->VolPath, pInfo->VolNames, dwSize, &dwSize)) 137 | { 138 | free(pInfo->VolNames); 139 | pInfo->VolNames = NULL; 140 | } 141 | } 142 | } 143 | } 144 | 145 | static BOOL 146 | GetDriveByVolume(BOOL bIsCdRom, HANDLE hVolume, DWORD* pDrive) 147 | { 148 | DWORD dwSize = 0; 149 | STORAGE_DEVICE_NUMBER sdnDiskNumber = { 0 }; 150 | 151 | if (!DeviceIoControl(hVolume, IOCTL_STORAGE_GET_DEVICE_NUMBER, 152 | NULL, 0, &sdnDiskNumber, (DWORD)(sizeof(STORAGE_DEVICE_NUMBER)), &dwSize, NULL)) 153 | return FALSE; 154 | *pDrive = sdnDiskNumber.DeviceNumber; 155 | switch (sdnDiskNumber.DeviceType) 156 | { 157 | case FILE_DEVICE_CD_ROM: 158 | //case FILE_DEVICE_CD_ROM_FILE_SYSTEM: 159 | case FILE_DEVICE_DVD: 160 | return bIsCdRom ? TRUE : FALSE; 161 | case FILE_DEVICE_DISK: 162 | //case FILE_DEVICE_DISK_FILE_SYSTEM: 163 | //case FILE_DEVICE_FILE_SYSTEM: 164 | return bIsCdRom ? FALSE : TRUE; 165 | } 166 | return FALSE; 167 | } 168 | 169 | static UINT64 170 | GetDiskSize(HANDLE hDisk) 171 | { 172 | DWORD dwBytes; 173 | UINT64 Size = 0; 174 | GET_LENGTH_INFORMATION LengthInfo = { 0 }; 175 | if (DeviceIoControl(hDisk, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, 176 | &LengthInfo, sizeof(LengthInfo), &dwBytes, NULL)) 177 | Size = LengthInfo.Length.QuadPart; 178 | return Size; 179 | } 180 | 181 | static BOOL 182 | GetDiskPartMap(HANDLE hDisk, BOOL bIsCdRom, PHY_DRIVE_INFO* pInfo) 183 | { 184 | DRIVE_LAYOUT_INFORMATION_EX* pLayout = (DRIVE_LAYOUT_INFORMATION_EX*)mBuf.c; 185 | DWORD dwBytes = DISKLIB_BUFSZ; 186 | 187 | if (bIsCdRom) 188 | goto fail; 189 | 190 | if (!DeviceIoControl(hDisk, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, NULL, 0, 191 | pLayout, dwBytes, &dwBytes, NULL)) 192 | goto fail; 193 | if (dwBytes < sizeof(DRIVE_LAYOUT_INFORMATION_EX) - sizeof(PARTITION_INFORMATION_EX)) 194 | goto fail; 195 | 196 | pInfo->PartMap = pLayout->PartitionStyle; 197 | switch (pInfo->PartMap) 198 | { 199 | case PARTITION_STYLE_MBR: 200 | if (pLayout->PartitionCount >= 4) 201 | { 202 | int i; 203 | for (i = 0; i < 4; i++) 204 | pInfo->MbrLba[i] = (DWORD)(pLayout->PartitionEntry[i].StartingOffset.QuadPart >> 9); 205 | } 206 | memcpy(pInfo->MbrSignature, &pLayout->Mbr.Signature, sizeof(DWORD)); 207 | break; 208 | case PARTITION_STYLE_GPT: 209 | memcpy(pInfo->GptGuid, &pLayout->Gpt.DiskId, sizeof(GUID)); 210 | break; 211 | default: 212 | goto fail; 213 | } 214 | return TRUE; 215 | 216 | fail: 217 | pInfo->PartMap = PARTITION_STYLE_RAW; 218 | return FALSE; 219 | } 220 | 221 | static BOOL 222 | CheckSsd(HANDLE hDisk, PHY_DRIVE_INFO* pInfo) 223 | { 224 | OSVERSIONINFOEXW osInfo = { 0 }; 225 | GetNtVersion(&osInfo); 226 | if (osInfo.dwMajorVersion >= 6) 227 | { 228 | DWORD dwBytes; 229 | STORAGE_PROPERTY_QUERY propQuery = { .QueryType = PropertyStandardQuery, .PropertyId = StorageDeviceSeekPenaltyProperty }; 230 | DEVICE_SEEK_PENALTY_DESCRIPTOR dspd = { 0 }; 231 | if (hDisk && hDisk != INVALID_HANDLE_VALUE) 232 | { 233 | if (DeviceIoControl(hDisk, IOCTL_STORAGE_QUERY_PROPERTY, &propQuery, sizeof(propQuery), 234 | &dspd, sizeof(dspd), &dwBytes, NULL)) 235 | { 236 | return (dspd.IncursSeekPenalty == FALSE); 237 | } 238 | } 239 | } 240 | if (pInfo->BusType == BusTypeNvme) 241 | return TRUE; 242 | return FALSE; 243 | } 244 | 245 | static VOID 246 | RemoveTrailingBackslash(WCHAR* lpszPath) 247 | { 248 | size_t len = wcslen(lpszPath); 249 | if (len < 1 || lpszPath[len - 1] != L'\\') 250 | return; 251 | lpszPath[len - 1] = L'\0'; 252 | } 253 | 254 | static VOID 255 | TrimString(CHAR* str) 256 | { 257 | char* p1 = str; 258 | char* p2 = str; 259 | size_t len = strlen(str); 260 | while (len > 0) 261 | { 262 | if (!isblank(str[len - 1])) 263 | break; 264 | str[len - 1] = '\0'; 265 | len--; 266 | } 267 | while (isblank(*p1)) 268 | p1++; 269 | while (*p1) 270 | { 271 | if (!isprint(*p1)) 272 | *p1 = '?'; 273 | *p2++ = *p1++; 274 | } 275 | *p2++ = 0; 276 | } 277 | 278 | static int __cdecl 279 | CompareDiskId(const void* a, const void* b) 280 | { 281 | return ((int)((const PHY_DRIVE_INFO*)a)->Index) - ((int)((const PHY_DRIVE_INFO*)b)->Index); 282 | } 283 | 284 | typedef struct 285 | { 286 | DWORD cbSize; 287 | WCHAR DevicePath[512]; 288 | } MY_DEVIF_DETAIL_DATA; 289 | 290 | DWORD GetDriveInfoList(BOOL bIsCdRom, PHY_DRIVE_INFO** pDriveList) 291 | { 292 | DWORD i; 293 | BOOL bRet; 294 | DWORD dwBytes; 295 | PHY_DRIVE_INFO* pInfo; 296 | 297 | HANDLE hSearch; 298 | WCHAR cchVolume[MAX_PATH]; 299 | 300 | DWORD dwCount = 0; 301 | SP_DEVICE_INTERFACE_DATA ifData = { .cbSize = sizeof(SP_DEVICE_INTERFACE_DATA) }; 302 | MY_DEVIF_DETAIL_DATA detailData = { .cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) }; 303 | SP_DEVINFO_DATA infoData = { .cbSize = sizeof(SP_DEVINFO_DATA) }; 304 | GUID devGuid = bIsCdRom ? GUID_DEVINTERFACE_CDROM : GUID_DEVINTERFACE_DISK; 305 | HDEVINFO hDevInfo = SetupDiGetClassDevsW(&devGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); 306 | if (hDevInfo == INVALID_HANDLE_VALUE) 307 | ErrorMsg("SetupDiGetClassDevsW failed", -3); 308 | 309 | while (SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &devGuid, dwCount, &ifData)) 310 | dwCount++; 311 | if (dwCount == 0) 312 | { 313 | SetupDiDestroyDeviceInfoList(hDevInfo); 314 | return 0; 315 | } 316 | 317 | *pDriveList = calloc(dwCount, sizeof(PHY_DRIVE_INFO)); 318 | if (!*pDriveList) 319 | ErrorMsg("out of memory", -2); 320 | 321 | pInfo = *pDriveList; 322 | 323 | for (i = 0; i < dwCount; i++) 324 | { 325 | HANDLE hDrive = INVALID_HANDLE_VALUE; 326 | STORAGE_PROPERTY_QUERY Query = { 0 }; 327 | STORAGE_DESCRIPTOR_HEADER DevDescHeader = { 0 }; 328 | STORAGE_DEVICE_DESCRIPTOR* pDevDesc = NULL; 329 | STORAGE_DEVICE_NUMBER sdn; 330 | HANDLE hIfDev; 331 | 332 | if (!SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &devGuid, i, &ifData)) 333 | goto next_drive; 334 | if (!SetupDiGetDeviceInterfaceDetailW(hDevInfo, &ifData, (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)&detailData, 335 | sizeof(MY_DEVIF_DETAIL_DATA), NULL, &infoData)) 336 | goto next_drive; 337 | hIfDev = CreateFileW(detailData.DevicePath, 338 | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 339 | NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 340 | if (hIfDev == INVALID_HANDLE_VALUE || hIfDev == NULL) 341 | goto next_drive; 342 | bRet = DeviceIoControl(hIfDev, IOCTL_STORAGE_GET_DEVICE_NUMBER, 343 | NULL, 0, &sdn, (DWORD)(sizeof(STORAGE_DEVICE_NUMBER)), 344 | &dwBytes, NULL); 345 | CloseHandle(hIfDev); 346 | if (bRet == FALSE) 347 | goto next_drive; 348 | pInfo[i].Index = sdn.DeviceNumber; 349 | 350 | if (SetupDiGetDeviceInstanceIdW(hDevInfo, &infoData, mBuf.w, DISKLIB_BUFSZB, NULL)) 351 | wcsncpy_s(pInfo[i].HwID, MAX_PATH, mBuf.w, MAX_PATH); 352 | if (SetupDiGetDeviceRegistryPropertyW(hDevInfo, &infoData, SPDRP_FRIENDLYNAME, 353 | NULL, (PBYTE)mBuf.w, DISKLIB_BUFSZB, NULL) || 354 | SetupDiGetDeviceRegistryPropertyW(hDevInfo, &infoData, SPDRP_DEVICEDESC, 355 | NULL, (PBYTE)mBuf.w, DISKLIB_BUFSZB, NULL)) 356 | wcsncpy_s(pInfo[i].HwName, MAX_PATH, mBuf.w, MAX_PATH); 357 | 358 | hDrive = GetDiskHandleById(bIsCdRom, FALSE, pInfo[i].Index); 359 | 360 | if (!hDrive || hDrive == INVALID_HANDLE_VALUE) 361 | goto next_drive; 362 | 363 | if (!bIsCdRom) 364 | pInfo[i].Ssd = CheckSsd(hDrive, &pInfo[i]); 365 | 366 | Query.PropertyId = StorageDeviceProperty; 367 | Query.QueryType = PropertyStandardQuery; 368 | 369 | bRet = DeviceIoControl(hDrive, IOCTL_STORAGE_QUERY_PROPERTY, &Query, sizeof(Query), 370 | &DevDescHeader, sizeof(STORAGE_DESCRIPTOR_HEADER), &dwBytes, NULL); 371 | if (!bRet || DevDescHeader.Size < sizeof(STORAGE_DEVICE_DESCRIPTOR)) 372 | goto next_drive; 373 | 374 | pDevDesc = (STORAGE_DEVICE_DESCRIPTOR*)malloc(DevDescHeader.Size); 375 | if (!pDevDesc) 376 | goto next_drive; 377 | 378 | bRet = DeviceIoControl(hDrive, IOCTL_STORAGE_QUERY_PROPERTY, &Query, sizeof(Query), 379 | pDevDesc, DevDescHeader.Size, &dwBytes, NULL); 380 | if (!bRet) 381 | goto next_drive; 382 | 383 | pInfo[i].SizeInBytes = GetDiskSize(hDrive); 384 | pInfo[i].DeviceType = pDevDesc->DeviceType; 385 | pInfo[i].RemovableMedia = pDevDesc->RemovableMedia; 386 | pInfo[i].BusType = pDevDesc->BusType; 387 | 388 | if (pDevDesc->VendorIdOffset) 389 | { 390 | strcpy_s(pInfo[i].VendorId, MAX_PATH, 391 | (char*)pDevDesc + pDevDesc->VendorIdOffset); 392 | TrimString(pInfo[i].VendorId); 393 | } 394 | 395 | if (pDevDesc->ProductIdOffset) 396 | { 397 | strcpy_s(pInfo[i].ProductId, MAX_PATH, 398 | (char*)pDevDesc + pDevDesc->ProductIdOffset); 399 | TrimString(pInfo[i].ProductId); 400 | } 401 | 402 | if (pDevDesc->ProductRevisionOffset) 403 | { 404 | strcpy_s(pInfo[i].ProductRev, MAX_PATH, 405 | (char*)pDevDesc + pDevDesc->ProductRevisionOffset); 406 | TrimString(pInfo[i].ProductRev); 407 | } 408 | 409 | if (pDevDesc->SerialNumberOffset) 410 | { 411 | strcpy_s(pInfo[i].SerialNumber, MAX_PATH, 412 | (char*)pDevDesc + pDevDesc->SerialNumberOffset); 413 | TrimString(pInfo[i].SerialNumber); 414 | } 415 | 416 | GetDiskPartMap(hDrive, bIsCdRom, &pInfo[i]); 417 | 418 | next_drive: 419 | if (pDevDesc) 420 | free(pDevDesc); 421 | if (hDrive && hDrive != INVALID_HANDLE_VALUE) 422 | CloseHandle(hDrive); 423 | } 424 | SetupDiDestroyDeviceInfoList(hDevInfo); 425 | 426 | for (bRet = TRUE, hSearch = FindFirstVolumeW(cchVolume, MAX_PATH); 427 | bRet && hSearch != INVALID_HANDLE_VALUE; 428 | bRet = FindNextVolumeW(hSearch, cchVolume, MAX_PATH)) 429 | { 430 | DWORD dwIndex; 431 | HANDLE hVolume; 432 | RemoveTrailingBackslash(cchVolume); 433 | hVolume = CreateFileW(cchVolume, 0, 434 | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); 435 | if (!hVolume || hVolume == INVALID_HANDLE_VALUE) 436 | continue; 437 | if (!GetDriveByVolume(bIsCdRom, hVolume, &dwBytes)) 438 | { 439 | CloseHandle(hVolume); 440 | continue; 441 | } 442 | CloseHandle(hVolume); 443 | for (dwIndex = 0; dwIndex < dwCount; dwIndex++) 444 | { 445 | if (dwBytes == pInfo[dwIndex].Index) 446 | break; 447 | } 448 | if (dwIndex >= dwCount) 449 | continue; 450 | if (pInfo[dwIndex].VolCount % 4 == 0) 451 | pInfo[dwIndex].VolInfo = realloc(pInfo[dwIndex].VolInfo, 452 | sizeof(DISK_VOL_INFO) * (pInfo[dwIndex].VolCount + 4)); 453 | if (pInfo[dwIndex].VolInfo == NULL) 454 | ErrorMsg("out of memory", -1); 455 | FillVolumeInfo(&pInfo[dwIndex].VolInfo[pInfo[dwIndex].VolCount], cchVolume, &pInfo[dwIndex]); 456 | pInfo[dwIndex].VolCount++; 457 | } 458 | 459 | if (hSearch != INVALID_HANDLE_VALUE) 460 | FindVolumeClose(hSearch); 461 | 462 | qsort(pInfo, dwCount, sizeof(PHY_DRIVE_INFO), CompareDiskId); 463 | return dwCount; 464 | } 465 | 466 | VOID 467 | DestoryDriveInfoList(PHY_DRIVE_INFO* pInfo, DWORD dwCount) 468 | { 469 | if (pInfo == NULL) 470 | return; 471 | for (DWORD i = 0; i < dwCount; i++) 472 | { 473 | for (DWORD j = 0; j < pInfo[i].VolCount; j++) 474 | { 475 | free(pInfo[i].VolInfo[j].VolNames); 476 | } 477 | free(pInfo[i].VolInfo); 478 | } 479 | free(pInfo); 480 | } 481 | 482 | 483 | VOID 484 | GetNtVersion(LPOSVERSIONINFOEXW osInfo) 485 | { 486 | NTSTATUS(WINAPI * RtlGetVersion)(LPOSVERSIONINFOEXW) = NULL; 487 | HMODULE hMod = GetModuleHandleW(L"ntdll"); 488 | 489 | ZeroMemory(osInfo, sizeof(OSVERSIONINFOEXW)); 490 | 491 | if (hMod) 492 | *(FARPROC*)&RtlGetVersion = GetProcAddress(hMod, "RtlGetVersion"); 493 | 494 | if (RtlGetVersion) 495 | { 496 | osInfo->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); 497 | RtlGetVersion(osInfo); 498 | } 499 | } 500 | 501 | #define U_BUFSZ 0x10000 502 | static CHAR mUtf8Buf[U_BUFSZ + 1]; 503 | 504 | LPCSTR 505 | Ucs2ToUtf8(LPCWSTR src) 506 | { 507 | size_t i; 508 | CHAR* p = mUtf8Buf; 509 | ZeroMemory(mUtf8Buf, sizeof(mUtf8Buf)); 510 | for (i = 0; i < U_BUFSZ / 3; i++) 511 | { 512 | if (src[i] == 0x0000) 513 | break; 514 | else if (src[i] <= 0x007F) 515 | *p++ = (CHAR)src[i]; 516 | else if (src[i] <= 0x07FF) 517 | { 518 | *p++ = (src[i] >> 6) | 0xC0; 519 | *p++ = (src[i] & 0x3F) | 0x80; 520 | } 521 | else if (src[i] >= 0xD800 && src[i] <= 0xDFFF) 522 | { 523 | *p++ = 0; 524 | break; 525 | } 526 | else 527 | { 528 | *p++ = (src[i] >> 12) | 0xE0; 529 | *p++ = ((src[i] >> 6) & 0x3F) | 0x80; 530 | *p++ = (src[i] & 0x3F) | 0x80; 531 | } 532 | } 533 | return mUtf8Buf; 534 | } 535 | 536 | LPCSTR 537 | GetHumanSize(UINT64 ullSize, UINT64 ullBase) 538 | { 539 | UINT64 fsize = ullSize, frac = 0; 540 | unsigned units = 0; 541 | static char buf[48]; 542 | const char* umsg; 543 | const char* humanSizes[] = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB" }; 544 | 545 | while (fsize >= ullBase && units < 5) 546 | { 547 | frac = fsize % ullBase; 548 | fsize = fsize / ullBase; 549 | units++; 550 | } 551 | 552 | umsg = humanSizes[units]; 553 | 554 | if (units) 555 | { 556 | if (frac) 557 | frac = frac * 100 / ullBase; 558 | snprintf(buf, sizeof(buf), "%llu.%02llu %s", fsize, frac, umsg); 559 | } 560 | else 561 | snprintf(buf, sizeof(buf), "%llu %s", ullSize, umsg); 562 | return buf; 563 | } 564 | -------------------------------------------------------------------------------- /cditest/disklib.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Unlicense 2 | #pragma once 3 | 4 | #define VC_EXTRALEAN 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #define DISK_PROP_STR_LEN 42 12 | 13 | typedef struct _DISK_VOL_INFO 14 | { 15 | // Volume Info 16 | WCHAR VolPath[MAX_PATH]; 17 | WCHAR VolLabel[MAX_PATH]; 18 | WCHAR VolFs[MAX_PATH]; 19 | ULARGE_INTEGER VolFreeSpace; 20 | ULARGE_INTEGER VolTotalSpace; 21 | double VolUsage; 22 | LPWCH VolNames; 23 | // Partition Info 24 | UINT64 StartLba; 25 | DWORD PartNum; 26 | WCHAR PartType[DISK_PROP_STR_LEN]; 27 | WCHAR PartId[DISK_PROP_STR_LEN]; 28 | WCHAR PartFlag[DISK_PROP_STR_LEN]; 29 | BOOL BootIndicator; 30 | }DISK_VOL_INFO; 31 | 32 | typedef struct _PHY_DRIVE_INFO 33 | { 34 | DWORD Index; 35 | PARTITION_STYLE PartMap; // 0:MBR 1:GPT 2:RAW 36 | UINT64 SizeInBytes; 37 | BYTE DeviceType; 38 | BOOL RemovableMedia; 39 | BOOL Ssd; 40 | WCHAR HwID[MAX_PATH]; 41 | WCHAR HwName[MAX_PATH]; 42 | CHAR VendorId[MAX_PATH]; 43 | CHAR ProductId[MAX_PATH]; 44 | CHAR ProductRev[MAX_PATH]; 45 | CHAR SerialNumber[MAX_PATH]; 46 | STORAGE_BUS_TYPE BusType; 47 | // MBR 48 | UCHAR MbrSignature[4]; 49 | DWORD MbrLba[4]; 50 | // GPT 51 | UCHAR GptGuid[16]; 52 | 53 | DWORD VolCount; 54 | DISK_VOL_INFO* VolInfo; 55 | }PHY_DRIVE_INFO; 56 | 57 | static inline LPCSTR 58 | GetPartMapName(PARTITION_STYLE partMap) 59 | { 60 | switch (partMap) 61 | { 62 | case PARTITION_STYLE_MBR: return "MBR"; 63 | case PARTITION_STYLE_GPT: return "GPT"; 64 | } 65 | return "RAW"; 66 | } 67 | 68 | static inline LPCSTR 69 | GetBusTypeName(STORAGE_BUS_TYPE busType) 70 | { 71 | switch (busType) 72 | { 73 | case BusTypeUnknown: return "Unknown"; 74 | case BusTypeScsi: return "SCSI"; 75 | case BusTypeAtapi: return "Atapi"; 76 | case BusTypeAta: return "ATA"; 77 | case BusType1394: return "1394"; 78 | case BusTypeSsa: return "SSA"; 79 | case BusTypeFibre: return "Fibre"; 80 | case BusTypeUsb: return "USB"; 81 | case BusTypeRAID: return "RAID"; 82 | case BusTypeiScsi: return "iSCSI"; 83 | case BusTypeSas: return "SAS"; 84 | case BusTypeSata: return "SATA"; 85 | case BusTypeSd: return "SD"; 86 | case BusTypeMmc: return "MMC"; 87 | case BusTypeVirtual: return "Virtual"; 88 | case BusTypeFileBackedVirtual: return "File"; 89 | case BusTypeSpaces: return "Spaces"; 90 | case BusTypeNvme: return "NVMe"; 91 | case BusTypeSCM: return "SCM"; 92 | case BusTypeUfs: return "UFS"; 93 | } 94 | return "Unknown"; 95 | } 96 | 97 | DWORD GetDriveInfoList(BOOL bIsCdRom, PHY_DRIVE_INFO** pDriveList); 98 | VOID DestoryDriveInfoList(PHY_DRIVE_INFO* pInfo, DWORD dwCount); 99 | 100 | VOID GetNtVersion(LPOSVERSIONINFOEXW osInfo); 101 | LPCSTR Ucs2ToUtf8(LPCWSTR src); 102 | LPCSTR GetHumanSize(UINT64 ullSize, UINT64 ullBase); 103 | 104 | #ifdef __cplusplus 105 | } 106 | #endif 107 | -------------------------------------------------------------------------------- /cditest/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /libcdi.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.6.33801.468 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcdi", "libcdi\libcdi.vcxproj", "{F8C0B390-95BE-4B12-BA9B-48B4774FDDE4}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cditest", "cditest\cditest.vcxproj", "{20A977E8-8A04-4AC1-B050-D940E2E6BA13}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Release|ARM64 = Release|ARM64 13 | Release|x64 = Release|x64 14 | Release|x86 = Release|x86 15 | EndGlobalSection 16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 17 | {F8C0B390-95BE-4B12-BA9B-48B4774FDDE4}.Release|ARM64.ActiveCfg = Release|ARM64 18 | {F8C0B390-95BE-4B12-BA9B-48B4774FDDE4}.Release|ARM64.Build.0 = Release|ARM64 19 | {F8C0B390-95BE-4B12-BA9B-48B4774FDDE4}.Release|x64.ActiveCfg = Release|x64 20 | {F8C0B390-95BE-4B12-BA9B-48B4774FDDE4}.Release|x64.Build.0 = Release|x64 21 | {F8C0B390-95BE-4B12-BA9B-48B4774FDDE4}.Release|x86.ActiveCfg = Release|Win32 22 | {F8C0B390-95BE-4B12-BA9B-48B4774FDDE4}.Release|x86.Build.0 = Release|Win32 23 | {20A977E8-8A04-4AC1-B050-D940E2E6BA13}.Release|ARM64.ActiveCfg = Release|ARM64 24 | {20A977E8-8A04-4AC1-B050-D940E2E6BA13}.Release|ARM64.Build.0 = Release|ARM64 25 | {20A977E8-8A04-4AC1-B050-D940E2E6BA13}.Release|x64.ActiveCfg = Release|x64 26 | {20A977E8-8A04-4AC1-B050-D940E2E6BA13}.Release|x64.Build.0 = Release|x64 27 | {20A977E8-8A04-4AC1-B050-D940E2E6BA13}.Release|x86.ActiveCfg = Release|Win32 28 | {20A977E8-8A04-4AC1-B050-D940E2E6BA13}.Release|x86.Build.0 = Release|Win32 29 | EndGlobalSection 30 | GlobalSection(SolutionProperties) = preSolution 31 | HideSolutionNode = FALSE 32 | EndGlobalSection 33 | GlobalSection(ExtensibilityGlobals) = postSolution 34 | SolutionGuid = {E0565045-282A-408A-A099-CE45AE126AB2} 35 | EndGlobalSection 36 | EndGlobal 37 | -------------------------------------------------------------------------------- /libcdi/DnpService.h: -------------------------------------------------------------------------------- 1 | // http://www.dinop.com/vc/service_ctrl.html (ja) 2 | 3 | #pragma once 4 | 5 | #include 6 | #include "atlstr.h" 7 | 8 | class CDnpService 9 | { 10 | // 11 | // サービスの起動/停止用スレッドクラス 12 | // 13 | class CServiceThread 14 | { 15 | public: 16 | CServiceThread() 17 | { 18 | _bCancel = false; 19 | } 20 | 21 | private: 22 | 23 | bool _bCancel; //サービスの起動/停止処理中断用変数、trueなら中断開始 24 | CComAutoCriticalSection _secbCancel; //サービスの起動/停止処理中断用クリティカルセクション 25 | 26 | public: 27 | 28 | // 29 | // サービスの起動/停止処理中断用関数 30 | // 31 | // 中断したい場合はIsCancel(true,true)を呼び出す 32 | // 33 | bool IsCancel(bool bSave=false,bool bNewValue=false) 34 | { 35 | bool ret; 36 | 37 | _secbCancel.Lock(); 38 | if(bSave) 39 | { 40 | _bCancel = bNewValue; 41 | ret = true; 42 | } 43 | else 44 | ret = _bCancel; 45 | _secbCancel.Unlock(); 46 | 47 | return ret; 48 | } 49 | 50 | 51 | 52 | // 53 | // サービスの簡易コントロール 54 | // 55 | // そのまま呼び出すとサービスが起動/停止するまで無限ループで待機する。 56 | // スレッド中で呼び出し、IsCancel()を利用することで無限ループに陥らない 57 | // コントロールが可能。 58 | // 59 | bool EasyStartStop(LPCTSTR pszName, bool b) 60 | { 61 | //bool ret = false; 62 | BOOL bRet = FALSE; 63 | SC_HANDLE hManager = NULL; 64 | SC_HANDLE hService = NULL; 65 | SERVICE_STATUS sStatus; 66 | 67 | hManager = ::OpenSCManager(NULL,NULL,GENERIC_EXECUTE); 68 | if(hManager == NULL) 69 | { 70 | return false; 71 | } 72 | 73 | hService = ::OpenService(hManager, pszName, SERVICE_START | SERVICE_QUERY_STATUS); 74 | if(hService == NULL) 75 | { 76 | if(hManager){::CloseServiceHandle(hManager);} 77 | return false; 78 | } 79 | 80 | ::ZeroMemory(&sStatus,sizeof(SERVICE_STATUS)); 81 | bRet = ::QueryServiceStatus(hService,&sStatus); 82 | if(bRet == FALSE) 83 | { 84 | if(hService){::CloseServiceHandle(hService);} 85 | if(hManager){::CloseServiceHandle(hManager);} 86 | return false; 87 | } 88 | 89 | if(sStatus.dwCurrentState == SERVICE_RUNNING) 90 | { 91 | if(hService){::CloseServiceHandle(hService);} 92 | if(hManager){::CloseServiceHandle(hManager);} 93 | return true; 94 | } 95 | 96 | CString cstr; 97 | cstr.Format(_T("sStatus.dwCurrentState:%08X"), sStatus.dwCurrentState); 98 | DebugPrint(cstr); 99 | 100 | //サービス開始要求 101 | DebugPrint(_T("StartService - 1")); 102 | bRet = ::StartService(hService, NULL, NULL); 103 | 104 | //開始まで無限ループで待機 105 | DebugPrint(_T("QueryServiceStatus - 1")); 106 | int count = 0; 107 | while(::QueryServiceStatus(hService, &sStatus)) 108 | { 109 | // 無限ループを回避 (最大 1 秒間 WMI の初期化を待つ) 110 | if(count >= 4) 111 | { 112 | break; 113 | } 114 | 115 | if(sStatus.dwCurrentState == SERVICE_RUNNING) 116 | { 117 | DebugPrint(_T("StartService Completed : SERVICE_RUNNING")); 118 | if(hService){::CloseServiceHandle(hService);} 119 | if(hManager){::CloseServiceHandle(hManager);} 120 | return true; 121 | } 122 | 123 | ::Sleep(100 * count); 124 | DebugPrint(_T("Sleep")); 125 | count++; 126 | } 127 | 128 | // サービスの起動モードを auto に強制変更 129 | ShellExecute(NULL, NULL, _T("sc"), _T("config Winmgmt start= auto"), NULL, SW_HIDE); 130 | count = 0; 131 | DebugPrint(_T("QueryServiceStatus - 2")); 132 | while(::QueryServiceStatus(hService, &sStatus)) 133 | { 134 | //サービス開始要求 135 | DebugPrint(_T("StartService - 2")); 136 | ::StartService(hService, NULL, NULL); 137 | 138 | // 無限ループを回避 (最大 5 秒間 WMI の初期化を待つ) 139 | if(count >= 10) 140 | { 141 | break; 142 | } 143 | 144 | if(sStatus.dwCurrentState == SERVICE_RUNNING) 145 | { 146 | DebugPrint(_T("StartService Completed : SERVICE_RUNNING")); 147 | if(hService){::CloseServiceHandle(hService);} 148 | if(hManager){::CloseServiceHandle(hManager);} 149 | return true; 150 | } 151 | 152 | ::Sleep(500); 153 | DebugPrint(_T("Sleep")); 154 | count++; 155 | } 156 | 157 | if(hService){::CloseServiceHandle(hService);} 158 | if(hManager){::CloseServiceHandle(hManager);} 159 | return false; 160 | } 161 | }; 162 | 163 | 164 | public: 165 | 166 | 167 | // 168 | // サービスの簡易コントロール 169 | // 170 | // サービスが起動/停止するまで無限ループで待機する。 171 | // 172 | bool EasyStartStop(LPCTSTR pszName,bool bStart) 173 | { 174 | CServiceThread cThread; 175 | 176 | return cThread.EasyStartStop(pszName,bStart); 177 | } 178 | 179 | 180 | // 181 | // サービスの簡易起動 182 | // 183 | // サービスが起動するまで無限ループで待機する。 184 | // 185 | bool EasyStart(LPCTSTR pszName) 186 | { 187 | return EasyStartStop(pszName,true); 188 | } 189 | 190 | // 191 | // サービスの簡易停止 192 | // 193 | // サービスが停止するまで無限ループで待機する。 194 | // 195 | bool EasyStop(LPCTSTR pszName) 196 | { 197 | return EasyStartStop(pszName,false); 198 | } 199 | 200 | 201 | // 202 | // サービスの簡易再起動 203 | // 204 | // サービスが再起動するまで無限ループで待機する。 205 | // 206 | bool EasyRestart(LPCTSTR pszName) 207 | { 208 | bool ret; 209 | CServiceThread cThread; 210 | 211 | ret = cThread.EasyStartStop(pszName,false); 212 | if(ret) 213 | ret = cThread.EasyStartStop(pszName,true); 214 | 215 | return ret; 216 | } 217 | 218 | 219 | 220 | // 221 | // 指定するサービスが動いているかのチェック 222 | // 223 | // falseの場合は"停止"とは限らない。サービスが存在しない場合などもfalseとなる。 224 | // 225 | bool IsServiceRunning(LPCTSTR pszName) 226 | { 227 | bool ret; 228 | BOOL bRet; 229 | SC_HANDLE hManager; 230 | SC_HANDLE hService; 231 | SERVICE_STATUS sStatus; 232 | 233 | ret = false; 234 | hManager = NULL; 235 | hService = NULL; 236 | while(1) //無限ループではない! 237 | { 238 | hManager = ::OpenSCManager(NULL,NULL,GENERIC_EXECUTE); 239 | ATLASSERT(hManager); 240 | if(hManager == NULL) 241 | break; 242 | 243 | hService = ::OpenService(hManager,pszName,SERVICE_QUERY_STATUS); 244 | ATLASSERT(hService); 245 | if(hService == NULL) 246 | break; 247 | 248 | ::ZeroMemory(&sStatus,sizeof(SERVICE_STATUS)); 249 | bRet = ::QueryServiceStatus(hService,&sStatus); 250 | ATLASSERT(bRet); 251 | if(bRet == FALSE) 252 | break; 253 | 254 | if(sStatus.dwCurrentState == SERVICE_RUNNING) 255 | ret = true; 256 | 257 | break; //必須 258 | } 259 | 260 | if(hService) 261 | ::CloseServiceHandle(hService); 262 | if(hManager) 263 | ::CloseServiceHandle(hManager); 264 | 265 | return ret; 266 | } 267 | }; 268 | -------------------------------------------------------------------------------- /libcdi/JMicronUsbRaidDef.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*/ 2 | // Author : hiyohiyo 3 | // Mail : hiyohiyo@crystalmark.info 4 | // Web : https://crystalmark.info/ 5 | // License : The MIT License 6 | /*---------------------------------------------------------------------------*/ 7 | 8 | #pragma once 9 | 10 | //----------------------------------------------------------------------------- 11 | // 12 | // Struct Defines 13 | // 14 | //----------------------------------------------------------------------------- 15 | 16 | #define NUMBER_ATA_SMART_ATTRIBUTES 30 17 | 18 | #pragma pack(push,1) 19 | 20 | typedef struct _IDENTIFY_DEVICE 21 | { 22 | WORD GeneralConfiguration; //0 23 | WORD LogicalCylinders; //1 Obsolete 24 | WORD SpecificConfiguration; //2 25 | WORD LogicalHeads; //3 Obsolete 26 | WORD Retired1[2]; //4-5 27 | WORD LogicalSectors; //6 Obsolete 28 | DWORD ReservedForCompactFlash; //7-8 29 | WORD Retired2; //9 30 | CHAR SerialNumber[20]; //10-19 31 | WORD Retired3; //20 32 | WORD BufferSize; //21 Obsolete 33 | WORD Obsolute4; //22 34 | CHAR FirmwareRev[8]; //23-26 35 | CHAR Model[40]; //27-46 36 | WORD MaxNumPerInterupt; //47 37 | WORD Reserved1; //48 38 | WORD Capabilities1; //49 39 | WORD Capabilities2; //50 40 | DWORD Obsolute5; //51-52 41 | WORD Field88and7064; //53 42 | WORD Obsolute6[5]; //54-58 43 | WORD MultSectorStuff; //59 44 | DWORD TotalAddressableSectors; //60-61 45 | WORD Obsolute7; //62 46 | WORD MultiWordDma; //63 47 | WORD PioMode; //64 48 | WORD MinMultiwordDmaCycleTime; //65 49 | WORD RecommendedMultiwordDmaCycleTime; //66 50 | WORD MinPioCycleTimewoFlowCtrl; //67 51 | WORD MinPioCycleTimeWithFlowCtrl; //68 52 | WORD Reserved2[6]; //69-74 53 | WORD QueueDepth; //75 54 | WORD SerialAtaCapabilities; //76 55 | WORD SerialAtaAdditionalCapabilities; //77 56 | WORD SerialAtaFeaturesSupported; //78 57 | WORD SerialAtaFeaturesEnabled; //79 58 | WORD MajorVersion; //80 59 | WORD MinorVersion; //81 60 | WORD CommandSetSupported1; //82 61 | WORD CommandSetSupported2; //83 62 | WORD CommandSetSupported3; //84 63 | WORD CommandSetEnabled1; //85 64 | WORD CommandSetEnabled2; //86 65 | WORD CommandSetDefault; //87 66 | WORD UltraDmaMode; //88 67 | WORD TimeReqForSecurityErase; //89 68 | WORD TimeReqForEnhancedSecure; //90 69 | WORD CurrentPowerManagement; //91 70 | WORD MasterPasswordRevision; //92 71 | WORD HardwareResetResult; //93 72 | WORD AcoustricManagement; //94 73 | WORD StreamMinRequestSize; //95 74 | WORD StreamingTimeDma; //96 75 | WORD StreamingAccessLatency; //97 76 | DWORD StreamingPerformance; //98-99 77 | ULONGLONG MaxUserLba; //100-103 78 | WORD StremingTimePio; //104 79 | WORD Reserved3; //105 80 | WORD SectorSize; //106 81 | WORD InterSeekDelay; //107 82 | WORD IeeeOui; //108 83 | WORD UniqueId3; //109 84 | WORD UniqueId2; //110 85 | WORD UniqueId1; //111 86 | WORD Reserved4[4]; //112-115 87 | WORD Reserved5; //116 88 | DWORD WordsPerLogicalSector; //117-118 89 | WORD Reserved6[8]; //119-126 90 | WORD RemovableMediaStatus; //127 91 | WORD SecurityStatus; //128 92 | WORD VendorSpecific[31]; //129-159 93 | WORD CfaPowerMode1; //160 94 | WORD ReservedForCompactFlashAssociation[7]; //161-167 95 | WORD DeviceNominalFormFactor; //168 96 | WORD DataSetManagement; //169 97 | WORD AdditionalProductIdentifier[4]; //170-173 98 | WORD Reserved7[2]; //174-175 99 | CHAR CurrentMediaSerialNo[60]; //176-205 100 | WORD SctCommandTransport; //206 101 | WORD ReservedForCeAta1[2]; //207-208 102 | WORD AlignmentOfLogicalBlocks; //209 103 | DWORD WriteReadVerifySectorCountMode3; //210-211 104 | DWORD WriteReadVerifySectorCountMode2; //212-213 105 | WORD NvCacheCapabilities; //214 106 | DWORD NvCacheSizeLogicalBlocks; //215-216 107 | WORD NominalMediaRotationRate; //217 108 | WORD Reserved8; //218 109 | WORD NvCacheOptions1; //219 110 | WORD NvCacheOptions2; //220 111 | WORD Reserved9; //221 112 | WORD TransportMajorVersionNumber; //222 113 | WORD TransportMinorVersionNumber; //223 114 | WORD ReservedForCeAta2[10]; //224-233 115 | WORD MinimumBlocksPerDownloadMicrocode; //234 116 | WORD MaximumBlocksPerDownloadMicrocode; //235 117 | WORD Reserved10[19]; //236-254 118 | WORD IntegrityWord; //255 119 | }IDENTIFY_DEVICE; 120 | 121 | typedef struct _SMART_THRESHOLD 122 | { 123 | BYTE Id; 124 | BYTE ThresholdValue; 125 | BYTE Reserved[10]; 126 | } SMART_THRESHOLD; 127 | 128 | /* 129 | typedef struct _SMART_ATTRIBUTE 130 | { 131 | BYTE Id; 132 | WORD StatusFlags; 133 | BYTE CurrentValue; 134 | BYTE WorstValue; 135 | BYTE RawValue[6]; 136 | BYTE Reserved; 137 | } SMART_ATTRIBUTE; 138 | */ 139 | 140 | typedef struct _SMART_READ_DATA 141 | { 142 | BYTE revision[2]; 143 | SMART_ATTRIBUTE attribute[NUMBER_ATA_SMART_ATTRIBUTES]; 144 | BYTE reserved[150]; 145 | } SMART_READ_DATA; 146 | 147 | typedef struct _SMART_READ_THRESHOLD 148 | { 149 | BYTE revision[2]; 150 | SMART_THRESHOLD threshold[NUMBER_ATA_SMART_ATTRIBUTES]; 151 | BYTE reserved[150]; 152 | } SMART_READ_THRESHOLD; 153 | 154 | typedef struct _BYTE512 155 | { 156 | BYTE b[512]; 157 | } BYTE512; 158 | 159 | typedef struct _NVME_IDENTIFY_DEVICE 160 | { 161 | CHAR Reserved1[4]; 162 | CHAR SerialNumber[20]; 163 | CHAR Model[40]; 164 | CHAR FirmwareRev[8]; 165 | CHAR Reserved2[9]; 166 | CHAR MinorVersion; 167 | SHORT MajorVersion; 168 | CHAR Reserved3[428]; 169 | }NVME_IDENTIFY_DEVICE; 170 | 171 | typedef union _UNION_IDENTIFY_DEVICE 172 | { 173 | IDENTIFY_DEVICE I; 174 | NVME_IDENTIFY_DEVICE N; 175 | BYTE512 B; 176 | } UNION_IDENTIFY_DEVICE; 177 | 178 | typedef union _UNION_SMART_ATTRIBUTE 179 | { 180 | SMART_READ_DATA A; 181 | BYTE512 B; 182 | } UNION_SMART_ATTRIBUTE; 183 | 184 | typedef union _UNION_SMART_THRESHOLD 185 | { 186 | SMART_READ_THRESHOLD T; 187 | BYTE512 B; 188 | } UNION_SMART_THRESHOLD; 189 | 190 | #define DISKNAME_LENGTH (40+1) 191 | #define MODELNAME_LENGTH (20+1) 192 | #define SERIALNUMBER_LENGTH (20+1) 193 | #define DISK_FIRMWAREVERSION_LENGTH 9 194 | 195 | typedef struct _NVME_PORT_40 196 | { 197 | uint8_t ModelName[41]; /* Model name of disk */ 198 | uint8_t SerialNumber[SERIALNUMBER_LENGTH]; /* Serial number of disk */ 199 | uint32_t SectorSize; /* 512 bytes or 4K */ 200 | uint32_t Capacity; /* Disk capacity */ 201 | uint32_t CapacityOffset; /* Disk capacity */ 202 | uint8_t DeviceState; /* Device State */ 203 | uint8_t RaidIndex; /* RAID Index */ 204 | uint8_t MemberIndex; /* Member Index */ 205 | uint8_t PortType; /* Port Type */ 206 | uint8_t PCIeSpeed; /* PCIe Speed */ 207 | uint8_t PCIeLANE; /* PCIe LANE */ 208 | uint16_t PortErrorStatus; /* NVMe port error status */ 209 | uint8_t DiskType; 210 | } NVME_PORT_40; 211 | 212 | typedef struct _NVME_PORT_20 213 | { 214 | uint8_t ModelName[21]; /* Model name of disk */ 215 | uint8_t SerialNumber[SERIALNUMBER_LENGTH]; /* Serial number of disk */ 216 | uint32_t SectorSize; /* 512 bytes or 4K */ 217 | uint32_t Capacity; /* Disk capacity */ 218 | uint32_t CapacityOffset; /* Disk capacity */ 219 | uint8_t DeviceState; /* Device State */ 220 | uint8_t RaidIndex; /* RAID Index */ 221 | uint8_t MemberIndex; /* Member Index */ 222 | uint8_t PortType; /* Port Type */ 223 | uint8_t PCIeSpeed; /* PCIe Speed */ 224 | uint8_t PCIeLANE; /* PCIe LANE */ 225 | uint16_t PortErrorStatus; /* NVMe port error status */ 226 | uint8_t DiskType; 227 | } NVME_PORT_20; 228 | 229 | typedef struct _NVME_ID 230 | { 231 | uint16_t PCIeVID; 232 | uint16_t PCIeSubSysVID; 233 | uint8_t ControllerMultIO; 234 | uint8_t MaxTransferSize; 235 | uint16_t ControllerID; 236 | uint8_t FirmwareRevision[8]; 237 | uint8_t FGUID[16]; 238 | uint16_t WarnTemperatureThreshold; 239 | uint16_t CriticalTemperatureThreshold; 240 | uint16_t MinThermalTemperature; 241 | uint16_t MaxThermalTemperature; 242 | uint32_t NumOFNamespace; 243 | uint8_t IeeeOuiID[3]; 244 | } NVME_ID; 245 | 246 | #pragma pack(pop) 247 | 248 | //----------------------------------------------------------------------------- 249 | // 250 | // Type Defines 251 | // 252 | //----------------------------------------------------------------------------- 253 | 254 | // JMicron JMS56X API 255 | typedef DWORD(WINAPI* _GetDllVersionJMS56X) (PBYTE major, PBYTE minor, PBYTE revision, PBYTE release); 256 | typedef int(WINAPI* _GetControllerCountJMS56X) (); 257 | typedef BOOL(WINAPI* _GetSmartInfoJMS56X) (int index, unsigned char port, UNION_SMART_ATTRIBUTE* attribute, UNION_SMART_THRESHOLD* threshold); 258 | typedef BOOL(WINAPI* _GetIdentifyInfoJMS56X) (int index, unsigned char port, UNION_IDENTIFY_DEVICE* identify); 259 | 260 | // JMicron JMB39X API 261 | typedef DWORD(WINAPI* _GetDllVersionJMB39X) (PBYTE major, PBYTE minor, PBYTE revision, PBYTE release); 262 | typedef int(WINAPI* _GetControllerCountJMB39X) (); 263 | typedef BOOL(WINAPI* _GetSmartInfoJMB39X) (int index, unsigned char port, UNION_SMART_ATTRIBUTE* attribute, UNION_SMART_THRESHOLD* threshold); 264 | typedef BOOL(WINAPI* _GetIdentifyInfoJMB39X) (int index, unsigned char port, UNION_IDENTIFY_DEVICE* identify); 265 | 266 | // JMicron JMS586_Old API 267 | typedef DWORD(WINAPI* _GetDllVersionJMS586_20) (PBYTE major, PBYTE minor, PBYTE revision, PBYTE release); 268 | typedef int(WINAPI* _GetControllerCountJMS586_20) (); 269 | typedef BOOL(WINAPI* _GetSmartInfoJMS586_20) (int index, unsigned char port, UNION_SMART_ATTRIBUTE* attribute, UNION_SMART_THRESHOLD* threshold); 270 | typedef BOOL(WINAPI* _GetIdentifyInfoJMS586_20) (int index, unsigned char port, UNION_IDENTIFY_DEVICE* identify); 271 | 272 | typedef BOOL(WINAPI* _GetNVMePortInfoJMS586_20) (int index, unsigned char port, NVME_PORT_20* nvmePort); 273 | typedef BOOL(WINAPI* _GetNVMeSmartInfoJMS586_20) (int index, unsigned char port, UNION_SMART_ATTRIBUTE* smartInfo); 274 | 275 | // JMicron JMS586_New API 276 | typedef DWORD(WINAPI* _GetDllVersionJMS586_40) (PBYTE major, PBYTE minor, PBYTE revision, PBYTE release); 277 | typedef int(WINAPI* _GetControllerCountJMS586_40) (); 278 | typedef BOOL(WINAPI* _GetSmartInfoJMS586_40) (BYTE index, unsigned char port, UNION_SMART_ATTRIBUTE* attribute, UNION_SMART_THRESHOLD* threshold); 279 | typedef BOOL(WINAPI* _GetIdentifyInfoJMS586_40) (BYTE index, unsigned char port, UNION_IDENTIFY_DEVICE* identify); 280 | 281 | typedef BOOL(WINAPI* _GetNVMePortInfoJMS586_40) (BYTE index, unsigned char port, NVME_PORT_40* nvmePort); 282 | typedef BOOL(WINAPI* _GetNVMeSmartInfoJMS586_40) (BYTE index, unsigned char port, UNION_SMART_ATTRIBUTE* smartInfo); 283 | typedef BOOL(WINAPI* _GetNVMeIdInfoJMS586_40) (BYTE index, unsigned char port, NVME_ID* nvmeId); 284 | typedef BOOL(WINAPI* _ControllerSerialNum2IdJMS586_40) (BYTE csn, BYTE* cid); 285 | 286 | -------------------------------------------------------------------------------- /libcdi/JMicronUsbRaidInit.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*/ 2 | // Author : hiyohiyo 3 | // Mail : hiyohiyo@crystalmark.info 4 | // Web : https://crystalmark.info/ 5 | // License : The MIT License 6 | /*---------------------------------------------------------------------------*/ 7 | 8 | #pragma once 9 | 10 | //----------------------------------------------------------------------------- 11 | // 12 | // Prototypes 13 | // 14 | //----------------------------------------------------------------------------- 15 | 16 | BOOL InitializeJMS56X(HMODULE* hModule); 17 | BOOL DeinitializeJMS56X(HMODULE* hModule); 18 | 19 | BOOL InitializeJMB39X(HMODULE* hModule); 20 | BOOL DeinitializeJMB39X(HMODULE* hModule); 21 | 22 | BOOL InitializeJMS586_20(HMODULE* hModule); 23 | BOOL DeinitializeJMS586_20(HMODULE* hModule); 24 | 25 | BOOL InitializeJMS586_40(HMODULE* hModule); 26 | BOOL DeinitializeJMS586_40(HMODULE* hModule); 27 | 28 | //----------------------------------------------------------------------------- 29 | // 30 | // Funtions 31 | // 32 | //----------------------------------------------------------------------------- 33 | 34 | _GetDllVersionJMS56X pGetDllVersionJMS56X = NULL; 35 | _GetControllerCountJMS56X pGetControllerCountJMS56X = NULL; 36 | _GetSmartInfoJMS56X pGetSmartInfoJMS56X = NULL; 37 | _GetIdentifyInfoJMS56X pGetIdentifyInfoJMS56X = NULL; 38 | 39 | _GetDllVersionJMB39X pGetDllVersionJMB39X = NULL; 40 | _GetControllerCountJMB39X pGetControllerCountJMB39X = NULL; 41 | _GetSmartInfoJMB39X pGetSmartInfoJMB39X = NULL; 42 | _GetIdentifyInfoJMB39X pGetIdentifyInfoJMB39X = NULL; 43 | 44 | _GetDllVersionJMS586_20 pGetDllVersionJMS586_20 = NULL; 45 | _GetControllerCountJMS586_20 pGetControllerCountJMS586_20 = NULL; 46 | _GetSmartInfoJMS586_20 pGetSmartInfoJMS586_20 = NULL; 47 | _GetIdentifyInfoJMS586_20 pGetIdentifyInfoJMS586_20 = NULL; 48 | _GetNVMePortInfoJMS586_20 pGetNVMePortInfoJMS586_20 = NULL; 49 | _GetNVMeSmartInfoJMS586_20 pGetNVMeSmartInfoJMS586_20 = NULL; 50 | 51 | _GetDllVersionJMS586_40 pGetDllVersionJMS586_40 = NULL; 52 | _GetControllerCountJMS586_40 pGetControllerCountJMS586_40 = NULL; 53 | _GetSmartInfoJMS586_40 pGetSmartInfoJMS586_40 = NULL; 54 | _GetIdentifyInfoJMS586_40 pGetIdentifyInfoJMS586_40 = NULL; 55 | _GetNVMePortInfoJMS586_40 pGetNVMePortInfoJMS586_40 = NULL; 56 | _GetNVMeSmartInfoJMS586_40 pGetNVMeSmartInfoJMS586_40 = NULL; 57 | _GetNVMeIdInfoJMS586_40 pGetNVMeIdInfoJMS586_40 = NULL; 58 | _ControllerSerialNum2IdJMS586_40 pControllerSerialNum2IdJMS586_40 = NULL; 59 | 60 | //----------------------------------------------------------------------------- 61 | // 62 | // Initialize 63 | // 64 | //----------------------------------------------------------------------------- 65 | 66 | BOOL InitializeJMS56X(HMODULE* hModule) 67 | { 68 | TCHAR fullPath[MAX_PATH] = {}; 69 | TCHAR drive[MAX_PATH] = {}; 70 | TCHAR path[MAX_PATH] = {}; 71 | TCHAR dllPath[MAX_PATH] = {}; 72 | 73 | GetModuleFileNameW(NULL, fullPath, MAX_PATH); 74 | _wsplitpath_s(fullPath, drive, MAX_PATH, path, MAX_PATH, NULL, 0, NULL, 0); 75 | wcscat_s(dllPath, MAX_PATH, drive); 76 | wcscat_s(dllPath, MAX_PATH, path); 77 | wcscat_s(dllPath, MAX_PATH, DLL_DIR); 78 | 79 | #ifdef _M_ARM64 80 | wcscat_s(dllPath, MAX_PATH, L"JMS56xA64.dll"); 81 | #elif _M_X64 82 | wcscat_s(dllPath, MAX_PATH, L"JMS56x64.dll"); 83 | #else 84 | wcscat_s(dllPath, MAX_PATH, L"JMS56x86.dll"); 85 | #endif 86 | 87 | if (!CheckCodeSign(CERTNAME_JMS56X, dllPath)) { return FALSE; } 88 | * hModule = LoadLibraryW(dllPath); 89 | 90 | if (*hModule == NULL) 91 | { 92 | return FALSE; 93 | } 94 | 95 | //----------------------------------------------------------------------------- 96 | // GetProcAddress 97 | //----------------------------------------------------------------------------- 98 | pGetDllVersionJMS56X = (_GetDllVersionJMS56X)GetProcAddress(*hModule, "GetDllVersion"); 99 | pGetControllerCountJMS56X = (_GetControllerCountJMS56X)GetProcAddress(*hModule, "GetControllerCount"); 100 | pGetSmartInfoJMS56X = (_GetSmartInfoJMS56X)GetProcAddress(*hModule, "GetSmartInfoFx"); 101 | pGetIdentifyInfoJMS56X = (_GetIdentifyInfoJMS56X)GetProcAddress(*hModule, "GetIdentifyInfoFx"); 102 | 103 | //----------------------------------------------------------------------------- 104 | // Check Functions 105 | //----------------------------------------------------------------------------- 106 | if (!( pGetDllVersionJMS56X 107 | && pGetControllerCountJMS56X 108 | && pGetSmartInfoJMS56X 109 | && pGetIdentifyInfoJMS56X 110 | )) 111 | { 112 | FreeLibrary(*hModule); 113 | *hModule = NULL; 114 | return FALSE; 115 | } 116 | 117 | return TRUE; 118 | } 119 | 120 | BOOL InitializeJMB39X(HMODULE* hModule) 121 | { 122 | TCHAR fullPath[MAX_PATH] = {}; 123 | TCHAR drive[MAX_PATH] = {}; 124 | TCHAR path[MAX_PATH] = {}; 125 | TCHAR dllPath[MAX_PATH] = {}; 126 | 127 | GetModuleFileNameW(NULL, fullPath, MAX_PATH); 128 | _wsplitpath_s(fullPath, drive, MAX_PATH, path, MAX_PATH, NULL, 0, NULL, 0); 129 | wcscat_s(dllPath, MAX_PATH, drive); 130 | wcscat_s(dllPath, MAX_PATH, path); 131 | wcscat_s(dllPath, MAX_PATH, DLL_DIR); 132 | 133 | #ifdef _M_ARM64 134 | wcscat_s(dllPath, MAX_PATH, L"JMB39xA64.dll"); 135 | #elif _M_X64 136 | wcscat_s(dllPath, MAX_PATH, L"JMB39x64.dll"); 137 | #else 138 | wcscat_s(dllPath, MAX_PATH, L"JMB39x86.dll"); 139 | #endif 140 | 141 | if (!CheckCodeSign(CERTNAME_JMB39X, dllPath)) { return FALSE; } 142 | *hModule = LoadLibraryW(dllPath); 143 | 144 | if (*hModule == NULL) 145 | { 146 | return FALSE; 147 | } 148 | 149 | //----------------------------------------------------------------------------- 150 | // GetProcAddress 151 | //----------------------------------------------------------------------------- 152 | pGetDllVersionJMB39X = (_GetDllVersionJMB39X)GetProcAddress(*hModule, "GetDllVersion"); 153 | pGetControllerCountJMB39X = (_GetControllerCountJMB39X)GetProcAddress(*hModule, "GetControllerCount"); 154 | pGetSmartInfoJMB39X = (_GetSmartInfoJMB39X)GetProcAddress(*hModule, "GetSmartInfoFx"); 155 | pGetIdentifyInfoJMB39X = (_GetIdentifyInfoJMB39X)GetProcAddress(*hModule, "GetIdentifyInfoFx"); 156 | 157 | //----------------------------------------------------------------------------- 158 | // Check Functions 159 | //----------------------------------------------------------------------------- 160 | if (!( pGetDllVersionJMB39X 161 | && pGetControllerCountJMB39X 162 | && pGetSmartInfoJMB39X 163 | && pGetIdentifyInfoJMB39X 164 | )) 165 | { 166 | FreeLibrary(*hModule); 167 | *hModule = NULL; 168 | return FALSE; 169 | } 170 | 171 | return TRUE; 172 | } 173 | 174 | BOOL InitializeJMS586_20(HMODULE* hModule) 175 | { 176 | TCHAR fullPath[MAX_PATH] = {}; 177 | TCHAR drive[MAX_PATH] = {}; 178 | TCHAR path[MAX_PATH] = {}; 179 | TCHAR dllPath[MAX_PATH] = {}; 180 | 181 | GetModuleFileNameW(NULL, fullPath, MAX_PATH); 182 | _wsplitpath_s(fullPath, drive, MAX_PATH, path, MAX_PATH, NULL, 0, NULL, 0); 183 | wcscat_s(dllPath, MAX_PATH, drive); 184 | wcscat_s(dllPath, MAX_PATH, path); 185 | wcscat_s(dllPath, MAX_PATH, DLL_DIR); 186 | 187 | #ifdef _M_ARM64 188 | wcscat_s(dllPath, MAX_PATH, L"JMS586A64.dll"); 189 | #elif _M_X64 190 | wcscat_s(dllPath, MAX_PATH, L"JMS586x64.dll"); 191 | #else 192 | wcscat_s(dllPath, MAX_PATH, L"JMS586x86.dll"); 193 | #endif 194 | 195 | if (!CheckCodeSign(CERTNAME_JMS586_20, dllPath)) { return FALSE; } 196 | *hModule = LoadLibraryW(dllPath); 197 | 198 | if (*hModule == NULL) 199 | { 200 | return FALSE; 201 | } 202 | 203 | //----------------------------------------------------------------------------- 204 | // GetProcAddress 205 | //----------------------------------------------------------------------------- 206 | pGetDllVersionJMS586_20 = (_GetDllVersionJMS586_20)GetProcAddress(*hModule, "GetDllVersion"); 207 | pGetControllerCountJMS586_20 = (_GetControllerCountJMS586_20)GetProcAddress(*hModule, "GetControllerCount"); 208 | pGetSmartInfoJMS586_20 = (_GetSmartInfoJMS586_20)GetProcAddress(*hModule, "GetSmartInfoFx"); 209 | pGetIdentifyInfoJMS586_20 = (_GetIdentifyInfoJMS586_20)GetProcAddress(*hModule, "GetIdentifyInfoFx"); 210 | pGetNVMePortInfoJMS586_20 = (_GetNVMePortInfoJMS586_20)GetProcAddress(*hModule, "GetNVMePortInfoFx"); 211 | pGetNVMeSmartInfoJMS586_20 = (_GetNVMeSmartInfoJMS586_20)GetProcAddress(*hModule, "GetNVMeSmartInfoFx"); 212 | 213 | //----------------------------------------------------------------------------- 214 | // Check Functions 215 | //----------------------------------------------------------------------------- 216 | if (!(pGetDllVersionJMS586_20 217 | && pGetControllerCountJMS586_20 218 | && pGetSmartInfoJMS586_20 219 | && pGetIdentifyInfoJMS586_20 220 | && pGetNVMePortInfoJMS586_20 221 | && pGetNVMeSmartInfoJMS586_20 222 | )) 223 | { 224 | FreeLibrary(*hModule); 225 | *hModule = NULL; 226 | return FALSE; 227 | } 228 | 229 | return TRUE; 230 | } 231 | 232 | BOOL InitializeJMS586_40(HMODULE* hModule) 233 | { 234 | TCHAR fullPath[MAX_PATH] = {}; 235 | TCHAR drive[MAX_PATH] = {}; 236 | TCHAR path[MAX_PATH] = {}; 237 | TCHAR dllPath[MAX_PATH] = {}; 238 | 239 | GetModuleFileNameW(NULL, fullPath, MAX_PATH); 240 | _wsplitpath_s(fullPath, drive, MAX_PATH, path, MAX_PATH, NULL, 0, NULL, 0); 241 | wcscat_s(dllPath, MAX_PATH, drive); 242 | wcscat_s(dllPath, MAX_PATH, path); 243 | wcscat_s(dllPath, MAX_PATH, DLL_DIR); 244 | 245 | #ifdef _M_ARM64 246 | wcscat_s(dllPath, MAX_PATH, L"JMS586_40A64.dll"); 247 | #elif _M_X64 248 | wcscat_s(dllPath, MAX_PATH, L"JMS586_40x64.dll"); 249 | #else 250 | wcscat_s(dllPath, MAX_PATH, L"JMS586_40x86.dll"); 251 | #endif 252 | 253 | if (!CheckCodeSign(CERTNAME_JMS586_40, dllPath)) { return FALSE; } 254 | *hModule = LoadLibraryW(dllPath); 255 | 256 | if (*hModule == NULL) 257 | { 258 | return FALSE; 259 | } 260 | 261 | //----------------------------------------------------------------------------- 262 | // GetProcAddress 263 | //----------------------------------------------------------------------------- 264 | pGetDllVersionJMS586_40 = (_GetDllVersionJMS586_40)GetProcAddress(*hModule, "GetDllVersion"); 265 | pGetControllerCountJMS586_40 = (_GetControllerCountJMS586_40)GetProcAddress(*hModule, "GetControllerCount"); 266 | pGetSmartInfoJMS586_40 = (_GetSmartInfoJMS586_40)GetProcAddress(*hModule, "GetSmartInfoFx"); 267 | pGetIdentifyInfoJMS586_40 = (_GetIdentifyInfoJMS586_40)GetProcAddress(*hModule, "GetIdentifyInfoFx"); 268 | pGetNVMePortInfoJMS586_40 = (_GetNVMePortInfoJMS586_40)GetProcAddress(*hModule, "GetNVMePortInfoFx"); 269 | pGetNVMeSmartInfoJMS586_40 = (_GetNVMeSmartInfoJMS586_40)GetProcAddress(*hModule, "GetNVMeSmartInfoFx"); 270 | pGetNVMeIdInfoJMS586_40 = (_GetNVMeIdInfoJMS586_40)GetProcAddress(*hModule, "GetNVMeIdInfoFx"); 271 | pControllerSerialNum2IdJMS586_40 = (_ControllerSerialNum2IdJMS586_40)GetProcAddress(*hModule, "ControllerSerialNum2IdFx"); 272 | 273 | //----------------------------------------------------------------------------- 274 | // Check Functions 275 | //----------------------------------------------------------------------------- 276 | if (!(pGetDllVersionJMS586_40 277 | && pGetControllerCountJMS586_40 278 | && pGetSmartInfoJMS586_40 279 | && pGetIdentifyInfoJMS586_40 280 | && pGetNVMePortInfoJMS586_40 281 | && pGetNVMeSmartInfoJMS586_40 282 | && pGetNVMeIdInfoJMS586_40 283 | && pControllerSerialNum2IdJMS586_40 284 | )) 285 | { 286 | FreeLibrary(*hModule); 287 | *hModule = NULL; 288 | return FALSE; 289 | } 290 | 291 | return TRUE; 292 | } 293 | 294 | 295 | //----------------------------------------------------------------------------- 296 | // 297 | // Deinitialize 298 | // 299 | //----------------------------------------------------------------------------- 300 | 301 | BOOL DeinitializeJMS56X(HMODULE* hModule) 302 | { 303 | BOOL result = FALSE; 304 | 305 | if (*hModule == NULL) 306 | { 307 | return TRUE; 308 | } 309 | else 310 | { 311 | result = FreeLibrary(*hModule); 312 | *hModule = NULL; 313 | 314 | return result; 315 | } 316 | } 317 | 318 | BOOL DeinitializeJMB39X(HMODULE* hModule) 319 | { 320 | BOOL result = FALSE; 321 | 322 | if (*hModule == NULL) 323 | { 324 | return TRUE; 325 | } 326 | else 327 | { 328 | result = FreeLibrary(*hModule); 329 | *hModule = NULL; 330 | 331 | return result; 332 | } 333 | } 334 | 335 | BOOL DeinitializeJMS586_20(HMODULE* hModule) 336 | { 337 | BOOL result = FALSE; 338 | 339 | if (*hModule == NULL) 340 | { 341 | return TRUE; 342 | } 343 | else 344 | { 345 | result = FreeLibrary(*hModule); 346 | *hModule = NULL; 347 | 348 | return result; 349 | } 350 | } 351 | 352 | BOOL DeinitializeJMS586_40(HMODULE* hModule) 353 | { 354 | BOOL result = FALSE; 355 | 356 | if (*hModule == NULL) 357 | { 358 | return TRUE; 359 | } 360 | else 361 | { 362 | result = FreeLibrary(*hModule); 363 | *hModule = NULL; 364 | 365 | return result; 366 | } 367 | } -------------------------------------------------------------------------------- /libcdi/NVMeInterpreter.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*/ 2 | // Author : Minkyu Kim 3 | // Web : http://naraeon.net/ 4 | // https://github.com/ebangin127/ 5 | // License : MIT License 6 | /*---------------------------------------------------------------------------*/ 7 | 8 | #include "StdAfx.h" 9 | #include "nvmeinterpreter.h" 10 | 11 | void AddToATASmartBuf(SMART_ATTRIBUTE_LIST* ATASmartBuf, INT IdxInBuf, SMART_ATTRIBUTE AttrToAdd) 12 | { 13 | (*ATASmartBuf)[IdxInBuf] = AttrToAdd; 14 | } 15 | 16 | SMART_ATTRIBUTE SeperateCriticalWarningFrom(UCHAR* NVMeSmartBuf) 17 | { 18 | SMART_ATTRIBUTE attr = {}; 19 | attr.Id = 1; 20 | attr.RawValue[0] = NVMeSmartBuf[0]; 21 | return attr; 22 | } 23 | 24 | SMART_ATTRIBUTE SeperateTemperatureFrom(UCHAR* NVMeSmartBuf) 25 | { 26 | const int TemperatureStart = 1; 27 | SMART_ATTRIBUTE attr = {}; 28 | attr.Id = 2; 29 | attr.RawValue[0] = NVMeSmartBuf[TemperatureStart]; 30 | attr.RawValue[1] = NVMeSmartBuf[TemperatureStart + 1]; 31 | return attr; 32 | } 33 | 34 | SMART_ATTRIBUTE SeperateAvailableSpareFrom(UCHAR* NVMeSmartBuf) 35 | { 36 | const int AvailableSpareStart = 3; 37 | SMART_ATTRIBUTE attr = {}; 38 | attr.Id = 3; 39 | attr.RawValue[0] = NVMeSmartBuf[AvailableSpareStart]; 40 | return attr; 41 | } 42 | 43 | SMART_ATTRIBUTE SeperateAvailableSpareThresholdFrom(UCHAR* NVMeSmartBuf) 44 | { 45 | const int AvailableSpareThresholdStart = 4; 46 | SMART_ATTRIBUTE attr = {}; 47 | attr.Id = 4; 48 | attr.RawValue[0] = NVMeSmartBuf[AvailableSpareThresholdStart]; 49 | return attr; 50 | } 51 | 52 | SMART_ATTRIBUTE SeperatePercentageUsedFrom(UCHAR* NVMeSmartBuf) 53 | { 54 | const int PercentageUsedStart = 5; 55 | SMART_ATTRIBUTE attr = {}; 56 | attr.Id = 5; 57 | attr.RawValue[0] = NVMeSmartBuf[PercentageUsedStart]; 58 | return attr; 59 | } 60 | 61 | SMART_ATTRIBUTE SeperateDataUnitsReadFrom(UCHAR* NVMeSmartBuf) 62 | { 63 | const int DataUnitsReadStart = 32; 64 | SMART_ATTRIBUTE attr = {}; 65 | attr.Id = 6; 66 | memcpy(attr.RawValue, &NVMeSmartBuf[DataUnitsReadStart], sizeof(attr.RawValue)); 67 | return attr; 68 | } 69 | 70 | SMART_ATTRIBUTE SeperateDataUnitsWrittenFrom(UCHAR* NVMeSmartBuf) 71 | { 72 | const int DataUnitsWrittenStart = 48; 73 | SMART_ATTRIBUTE attr = {}; 74 | attr.Id = 7; 75 | memcpy(attr.RawValue, &NVMeSmartBuf[DataUnitsWrittenStart], sizeof(attr.RawValue)); 76 | return attr; 77 | } 78 | 79 | SMART_ATTRIBUTE SeperateHostReadCommandsFrom(UCHAR* NVMeSmartBuf) 80 | { 81 | const int ReadStart = 64; 82 | SMART_ATTRIBUTE attr = {}; 83 | attr.Id = 8; 84 | memcpy(attr.RawValue, &NVMeSmartBuf[ReadStart], sizeof(attr.RawValue)); 85 | return attr; 86 | } 87 | 88 | SMART_ATTRIBUTE SeperateHostWriteCommandsFrom(UCHAR* NVMeSmartBuf) 89 | { 90 | const int WriteStart = 80; 91 | SMART_ATTRIBUTE attr = {}; 92 | attr.Id = 9; 93 | memcpy(attr.RawValue, &NVMeSmartBuf[WriteStart], sizeof(attr.RawValue)); 94 | return attr; 95 | } 96 | 97 | SMART_ATTRIBUTE SeperateControllerBusyTimeFrom(UCHAR* NVMeSmartBuf) 98 | { 99 | const int BusyTimeStart = 96; 100 | SMART_ATTRIBUTE attr = {}; 101 | attr.Id = 10; 102 | memcpy(attr.RawValue, &NVMeSmartBuf[BusyTimeStart], sizeof(attr.RawValue)); 103 | return attr; 104 | } 105 | 106 | SMART_ATTRIBUTE SeperatePowerCyclesFrom(UCHAR* NVMeSmartBuf) 107 | { 108 | const int PowerCycleStart = 112; 109 | SMART_ATTRIBUTE attr = {}; 110 | attr.Id = 11; 111 | memcpy(attr.RawValue, &NVMeSmartBuf[PowerCycleStart], sizeof(attr.RawValue)); 112 | return attr; 113 | } 114 | 115 | SMART_ATTRIBUTE SeperatePowerOnHoursFrom(UCHAR* NVMeSmartBuf) 116 | { 117 | const int PowerOnHoursStart = 128; 118 | SMART_ATTRIBUTE attr = {}; 119 | attr.Id = 12; 120 | memcpy(attr.RawValue, &NVMeSmartBuf[PowerOnHoursStart], sizeof(attr.RawValue)); 121 | return attr; 122 | } 123 | 124 | SMART_ATTRIBUTE SeperateUnsafeShutdownsFrom(UCHAR* NVMeSmartBuf) 125 | { 126 | const int UnsafeShutdownsStart = 144; 127 | SMART_ATTRIBUTE attr = {}; 128 | attr.Id = 13; 129 | memcpy(attr.RawValue, &NVMeSmartBuf[UnsafeShutdownsStart], sizeof(attr.RawValue)); 130 | return attr; 131 | } 132 | 133 | SMART_ATTRIBUTE SeperateMediaErrorsFrom(UCHAR* NVMeSmartBuf) 134 | { 135 | const int MediaErrorsStart = 160; 136 | SMART_ATTRIBUTE attr = {}; 137 | attr.Id = 14; 138 | memcpy(attr.RawValue, &NVMeSmartBuf[MediaErrorsStart], sizeof(attr.RawValue)); 139 | return attr; 140 | } 141 | 142 | SMART_ATTRIBUTE SeperateNumberOfErrorsFrom(UCHAR* NVMeSmartBuf) 143 | { 144 | const int NumberOfErrorsStart = 176; 145 | SMART_ATTRIBUTE attr = {}; 146 | attr.Id = 15; 147 | memcpy(attr.RawValue, &NVMeSmartBuf[NumberOfErrorsStart], sizeof(attr.RawValue)); 148 | return attr; 149 | } 150 | 151 | SMART_ATTRIBUTE SeperateWarningCompositeTemperatureTime(UCHAR* NVMeSmartBuf) 152 | { 153 | const int TemperatureTimeStart = 192; 154 | SMART_ATTRIBUTE attr = {}; 155 | attr.Id = 16; 156 | memcpy(attr.RawValue, &NVMeSmartBuf[TemperatureTimeStart], 4); 157 | return attr; 158 | } 159 | 160 | SMART_ATTRIBUTE SeperateCriticalCompositeTemperatureTime(UCHAR* NVMeSmartBuf) 161 | { 162 | const int TemperatureTimeStart = 196; 163 | SMART_ATTRIBUTE attr = {}; 164 | attr.Id = 17; 165 | memcpy(attr.RawValue, &NVMeSmartBuf[TemperatureTimeStart], 4); 166 | return attr; 167 | } 168 | 169 | void NVMeSmartToATASmart(UCHAR* NVMeSmartBuf, void* ATASmartBufUncasted) 170 | { 171 | SMART_ATTRIBUTE_LIST* ATASmartBuf = (SMART_ATTRIBUTE_LIST*) ATASmartBufUncasted; 172 | int IdxInBuf = 0; 173 | AddToATASmartBuf(ATASmartBuf, IdxInBuf++, SeperateCriticalWarningFrom(NVMeSmartBuf)); 174 | AddToATASmartBuf(ATASmartBuf, IdxInBuf++, SeperateTemperatureFrom(NVMeSmartBuf)); 175 | AddToATASmartBuf(ATASmartBuf, IdxInBuf++, SeperateAvailableSpareFrom(NVMeSmartBuf)); 176 | AddToATASmartBuf(ATASmartBuf, IdxInBuf++, SeperateAvailableSpareThresholdFrom(NVMeSmartBuf)); 177 | AddToATASmartBuf(ATASmartBuf, IdxInBuf++, SeperatePercentageUsedFrom(NVMeSmartBuf)); 178 | AddToATASmartBuf(ATASmartBuf, IdxInBuf++, SeperateDataUnitsReadFrom(NVMeSmartBuf)); 179 | AddToATASmartBuf(ATASmartBuf, IdxInBuf++, SeperateDataUnitsWrittenFrom(NVMeSmartBuf)); 180 | AddToATASmartBuf(ATASmartBuf, IdxInBuf++, SeperateHostReadCommandsFrom(NVMeSmartBuf)); 181 | AddToATASmartBuf(ATASmartBuf, IdxInBuf++, SeperateHostWriteCommandsFrom(NVMeSmartBuf)); 182 | AddToATASmartBuf(ATASmartBuf, IdxInBuf++, SeperateControllerBusyTimeFrom(NVMeSmartBuf)); 183 | AddToATASmartBuf(ATASmartBuf, IdxInBuf++, SeperatePowerCyclesFrom(NVMeSmartBuf)); 184 | AddToATASmartBuf(ATASmartBuf, IdxInBuf++, SeperatePowerOnHoursFrom(NVMeSmartBuf)); 185 | AddToATASmartBuf(ATASmartBuf, IdxInBuf++, SeperateUnsafeShutdownsFrom(NVMeSmartBuf)); 186 | AddToATASmartBuf(ATASmartBuf, IdxInBuf++, SeperateMediaErrorsFrom(NVMeSmartBuf)); 187 | AddToATASmartBuf(ATASmartBuf, IdxInBuf++, SeperateNumberOfErrorsFrom(NVMeSmartBuf)); 188 | NVMeTemperatureSensorSmartToATASmart(NVMeSmartBuf, ATASmartBuf); 189 | } 190 | 191 | void NVMeCompositeTemperatureSmartToATASmart(UCHAR* NVMeSmartBuf, void* ATASmartBufUncasted) { 192 | SMART_ATTRIBUTE_LIST* ATASmartBuf = (SMART_ATTRIBUTE_LIST*)ATASmartBufUncasted; 193 | int IdxInBuf = 15; 194 | AddToATASmartBuf(ATASmartBuf, IdxInBuf++, SeperateWarningCompositeTemperatureTime(NVMeSmartBuf)); 195 | AddToATASmartBuf(ATASmartBuf, IdxInBuf++, SeperateCriticalCompositeTemperatureTime(NVMeSmartBuf)); 196 | } 197 | 198 | void NVMeTemperatureSensorSmartToATASmart(UCHAR* NVMeSmartBuf, void* ATASmartBufUncasted) { 199 | SMART_ATTRIBUTE_LIST* ATASmartBuf = (SMART_ATTRIBUTE_LIST*)ATASmartBufUncasted; 200 | int IdxInBuf = 17; 201 | const int TemperatureSensorStart = 200; 202 | const int MaxSensors = 8; 203 | 204 | for (int i = 0; i < MaxSensors; i++) { 205 | SMART_ATTRIBUTE attr = {}; 206 | attr.Id = ++IdxInBuf; 207 | memcpy(attr.RawValue, &NVMeSmartBuf[TemperatureSensorStart + i*2], 2); 208 | if (attr.RawValue[0] || attr.RawValue[1]) { 209 | AddToATASmartBuf(ATASmartBuf, IdxInBuf, attr); 210 | } 211 | } 212 | } 213 | 214 | void NVMeThermalManagementTemperatureSmartToATASmart(UCHAR* NVMeSmartBuf, void* ATASmartBufUncasted) { 215 | SMART_ATTRIBUTE_LIST* ATASmartBuf = (SMART_ATTRIBUTE_LIST*)ATASmartBufUncasted; 216 | int IdxInBuf = 25; 217 | const int TemperatureSensorStart = 216; 218 | const int MaxEntries = 4; 219 | 220 | for (int i = 0; i < MaxEntries; i++) { 221 | SMART_ATTRIBUTE attr = {}; 222 | attr.Id = ++IdxInBuf; 223 | memcpy(attr.RawValue, &NVMeSmartBuf[TemperatureSensorStart + i*4], 4); 224 | AddToATASmartBuf(ATASmartBuf, IdxInBuf, attr); 225 | } 226 | } -------------------------------------------------------------------------------- /libcdi/NVMeInterpreter.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*/ 2 | // Author : Minkyu Kim 3 | // Web : http://naraeon.net/ 4 | // https://github.com/ebangin127/ 5 | // License : MIT License 6 | /*---------------------------------------------------------------------------*/ 7 | 8 | #pragma once 9 | #include 10 | 11 | static const int MAX_ATTRIBUTE = 30; 12 | static const int NVME_ATTRIBUTE = 30; 13 | 14 | #pragma pack(push,1) 15 | typedef struct _SMART_ATTRIBUTE 16 | { 17 | BYTE Id; 18 | WORD StatusFlags; 19 | BYTE CurrentValue; 20 | BYTE WorstValue; 21 | BYTE RawValue[6]; 22 | BYTE Reserved; 23 | } SMART_ATTRIBUTE; 24 | #pragma pack(pop) 25 | 26 | typedef SMART_ATTRIBUTE SMART_ATTRIBUTE_LIST[MAX_ATTRIBUTE]; 27 | 28 | void NVMeSmartToATASmart(UCHAR* NVMeSmartBuf, void* ATASmartBufUncasted); 29 | 30 | void NVMeCompositeTemperatureSmartToATASmart(UCHAR* NVMeSmartBuf, void* ATASmartBufUncasted); 31 | 32 | void NVMeTemperatureSensorSmartToATASmart(UCHAR* NVMeSmartBuf, void* ATASmartBufUncasted); 33 | 34 | void NVMeThermalManagementTemperatureSmartToATASmart(UCHAR* NVMeSmartBuf, void* ATASmartBufUncasted); -------------------------------------------------------------------------------- /libcdi/Priscilla/OsInfoFx.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*/ 2 | // Author : hiyohiyo 3 | // Mail : hiyohiyo@crystalmark.info 4 | // Web : https://crystalmark.info/ 5 | // License : MIT License 6 | /*---------------------------------------------------------------------------*/ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | ////------------------------------------------------ 13 | // OS Info 14 | ////------------------------------------------------ 15 | 16 | #if _MSC_VER > 1310 17 | BOOL IsWindowsVersionOrGreaterFx(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor = 0); 18 | BOOL IsWindowsBuildOrGreater(DWORD build); 19 | BOOL IsX64(); 20 | BOOL IsIa64(); 21 | BOOL IsArm32(); 22 | BOOL IsArm64(); 23 | BOOL IsWow64(); 24 | BOOL IsIe556(); 25 | BOOL IsDotNet2(); 26 | BOOL IsDotNet4(); 27 | BOOL IsDotNet48(); 28 | BOOL IsNT5(); 29 | BOOL IsNT6orLater(); 30 | BOOL IsWin2k(); 31 | BOOL IsWinXpOrLater(); 32 | BOOL IsWinXpLuna(); 33 | BOOL IsWin8orLater(); 34 | BOOL IsWin81orLater(); 35 | BOOL IsDarkModeSupport(); 36 | BOOL HasSidebar(); 37 | #endif 38 | 39 | #if _MSC_VER <= 1310 40 | #ifdef UNICODE 41 | BOOL IsCurrentUserLocalAdministrator(void); 42 | BOOL IsUserAdmin(VOID); 43 | #endif 44 | #endif 45 | 46 | BOOL IsNT3(); 47 | BOOL IsNT4(); 48 | BOOL IsWin9x(); 49 | BOOL IsWin95(); 50 | BOOL IsWin95First(); 51 | BOOL IsPC98(); 52 | BOOL IsNT51orlater(); 53 | BOOL IsRunningOnWine(); 54 | 55 | DWORD GetIeVersion(); 56 | // DWORD GetWin10Version(); 57 | void GetOsName(CString& osFullName, CString& osName, CString& osVersion, CString& osArchitecture); 58 | void GetOsNameWmi(CString& osFullName); 59 | 60 | ////------------------------------------------------ 61 | // Define 62 | ////------------------------------------------------ 63 | 64 | #define PRODUCT_UNDEFINED 0x00000000 65 | 66 | #define PRODUCT_ULTIMATE 0x00000001 67 | #define PRODUCT_HOME_BASIC 0x00000002 68 | #define PRODUCT_HOME_PREMIUM 0x00000003 69 | #define PRODUCT_ENTERPRISE 0x00000004 70 | #define PRODUCT_HOME_BASIC_N 0x00000005 71 | #define PRODUCT_BUSINESS 0x00000006 72 | #define PRODUCT_STANDARD_SERVER 0x00000007 73 | #define PRODUCT_DATACENTER_SERVER 0x00000008 74 | #define PRODUCT_SMALLBUSINESS_SERVER 0x00000009 75 | #define PRODUCT_ENTERPRISE_SERVER 0x0000000A 76 | #define PRODUCT_STARTER 0x0000000B 77 | #define PRODUCT_DATACENTER_SERVER_CORE 0x0000000C 78 | #define PRODUCT_STANDARD_SERVER_CORE 0x0000000D 79 | #define PRODUCT_ENTERPRISE_SERVER_CORE 0x0000000E 80 | #define PRODUCT_ENTERPRISE_SERVER_IA64 0x0000000F 81 | #define PRODUCT_BUSINESS_N 0x00000010 82 | #define PRODUCT_WEB_SERVER 0x00000011 83 | #define PRODUCT_CLUSTER_SERVER 0x00000012 84 | #define PRODUCT_HOME_SERVER 0x00000013 85 | #define PRODUCT_STORAGE_EXPRESS_SERVER 0x00000014 86 | #define PRODUCT_STORAGE_STANDARD_SERVER 0x00000015 87 | #define PRODUCT_STORAGE_WORKGROUP_SERVER 0x00000016 88 | #define PRODUCT_STORAGE_ENTERPRISE_SERVER 0x00000017 89 | #define PRODUCT_SERVER_FOR_SMALLBUSINESS 0x00000018 90 | #define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM 0x00000019 91 | #define PRODUCT_HOME_PREMIUM_N 0x0000001A 92 | #define PRODUCT_ENTERPRISE_N 0x0000001B 93 | #define PRODUCT_ULTIMATE_N 0x0000001C 94 | #define PRODUCT_WEB_SERVER_CORE 0x0000001D 95 | #define PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT 0x0000001E 96 | #define PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY 0x0000001F 97 | #define PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING 0x00000020 98 | #define PRODUCT_SERVER_FOUNDATION 0x00000021 99 | #define PRODUCT_HOME_PREMIUM_SERVER 0x00000022 100 | #define PRODUCT_SERVER_FOR_SMALLBUSINESS_V 0x00000023 101 | #define PRODUCT_STANDARD_SERVER_V 0x00000024 102 | #define PRODUCT_DATACENTER_SERVER_V 0x00000025 103 | #define PRODUCT_ENTERPRISE_SERVER_V 0x00000026 104 | #define PRODUCT_DATACENTER_SERVER_CORE_V 0x00000027 105 | #define PRODUCT_STANDARD_SERVER_CORE_V 0x00000028 106 | #define PRODUCT_ENTERPRISE_SERVER_CORE_V 0x00000029 107 | #define PRODUCT_HYPERV 0x0000002A 108 | #define PRODUCT_STORAGE_EXPRESS_SERVER_CORE 0x0000002B 109 | #define PRODUCT_STORAGE_STANDARD_SERVER_CORE 0x0000002C 110 | #define PRODUCT_STORAGE_WORKGROUP_SERVER_CORE 0x0000002D 111 | #define PRODUCT_STORAGE_ENTERPRISE_SERVER_CORE 0x0000002E 112 | #define PRODUCT_STARTER_N 0x0000002F 113 | #define PRODUCT_PROFESSIONAL 0x00000030 114 | #define PRODUCT_PROFESSIONAL_N 0x00000031 115 | #define PRODUCT_SB_SOLUTION_SERVER 0x00000032 116 | #define PRODUCT_SERVER_FOR_SB_SOLUTIONS 0x00000033 117 | #define PRODUCT_STANDARD_SERVER_SOLUTIONS 0x00000034 118 | #define PRODUCT_STANDARD_SERVER_SOLUTIONS_CORE 0x00000035 119 | #define PRODUCT_SB_SOLUTION_SERVER_EM 0x00000036 120 | #define PRODUCT_SERVER_FOR_SB_SOLUTIONS_EM 0x00000037 121 | #define PRODUCT_SOLUTION_EMBEDDEDSERVER 0x00000038 122 | #define PRODUCT_SOLUTION_EMBEDDEDSERVER_CORE 0x00000039 123 | #define PRODUCT_PROFESSIONAL_EMBEDDED 0x0000003A 124 | #define PRODUCT_ESSENTIALBUSINESS_SERVER_MGMT 0x0000003B 125 | #define PRODUCT_ESSENTIALBUSINESS_SERVER_ADDL 0x0000003C 126 | #define PRODUCT_ESSENTIALBUSINESS_SERVER_MGMTSVC 0x0000003D 127 | #define PRODUCT_ESSENTIALBUSINESS_SERVER_ADDLSVC 0x0000003E 128 | #define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE 0x0000003F 129 | #define PRODUCT_CLUSTER_SERVER_V 0x00000040 130 | #define PRODUCT_EMBEDDED 0x00000041 131 | #define PRODUCT_STARTER_E 0x00000042 132 | #define PRODUCT_HOME_BASIC_E 0x00000043 133 | #define PRODUCT_HOME_PREMIUM_E 0x00000044 134 | #define PRODUCT_PROFESSIONAL_E 0x00000045 135 | #define PRODUCT_ENTERPRISE_E 0x00000046 136 | #define PRODUCT_ULTIMATE_E 0x00000047 137 | #define PRODUCT_ENTERPRISE_EVALUATION 0x00000048 138 | #define PRODUCT_MULTIPOINT_STANDARD_SERVER 0x0000004C 139 | #define PRODUCT_MULTIPOINT_PREMIUM_SERVER 0x0000004D 140 | #define PRODUCT_STANDARD_EVALUATION_SERVER 0x0000004F 141 | #define PRODUCT_DATACENTER_EVALUATION_SERVER 0x00000050 142 | #define PRODUCT_ENTERPRISE_N_EVALUATION 0x00000054 143 | #define PRODUCT_EMBEDDED_AUTOMOTIVE 0x00000055 144 | #define PRODUCT_EMBEDDED_INDUSTRY_A 0x00000056 145 | #define PRODUCT_THINPC 0x00000057 146 | #define PRODUCT_EMBEDDED_A 0x00000058 147 | #define PRODUCT_EMBEDDED_INDUSTRY 0x00000059 148 | #define PRODUCT_EMBEDDED_E 0x0000005A 149 | #define PRODUCT_EMBEDDED_INDUSTRY_E 0x0000005B 150 | #define PRODUCT_EMBEDDED_INDUSTRY_A_E 0x0000005C 151 | #define PRODUCT_STORAGE_WORKGROUP_EVALUATION_SERVER 0x0000005F 152 | #define PRODUCT_STORAGE_STANDARD_EVALUATION_SERVER 0x00000060 153 | #define PRODUCT_CORE_ARM 0x00000061 154 | #define PRODUCT_CORE_N 0x00000062 155 | #define PRODUCT_CORE_COUNTRYSPECIFIC 0x00000063 156 | #define PRODUCT_CORE_SINGLELANGUAGE 0x00000064 157 | #define PRODUCT_CORE 0x00000065 158 | #define PRODUCT_PROFESSIONAL_WMC 0x00000067 159 | #define PRODUCT_EMBEDDED_INDUSTRY_EVAL 0x00000069 160 | #define PRODUCT_EMBEDDED_INDUSTRY_E_EVAL 0x0000006A 161 | #define PRODUCT_EMBEDDED_EVAL 0x0000006B 162 | #define PRODUCT_EMBEDDED_E_EVAL 0x0000006C 163 | #define PRODUCT_NANO_SERVER 0x0000006D 164 | #define PRODUCT_CLOUD_STORAGE_SERVER 0x0000006E 165 | #define PRODUCT_CORE_CONNECTED 0x0000006F 166 | #define PRODUCT_PROFESSIONAL_STUDENT 0x00000070 167 | #define PRODUCT_CORE_CONNECTED_N 0x00000071 168 | #define PRODUCT_PROFESSIONAL_STUDENT_N 0x00000072 169 | #define PRODUCT_CORE_CONNECTED_SINGLELANGUAGE 0x00000073 170 | #define PRODUCT_CORE_CONNECTED_COUNTRYSPECIFIC 0x00000074 171 | #define PRODUCT_CONNECTED_CAR 0x00000075 172 | #define PRODUCT_INDUSTRY_HANDHELD 0x00000076 173 | #define PRODUCT_PPI_PRO 0x00000077 174 | #define PRODUCT_ARM64_SERVER 0x00000078 175 | #define PRODUCT_EDUCATION 0x00000079 176 | #define PRODUCT_EDUCATION_N 0x0000007A 177 | #define PRODUCT_IOTUAP 0x0000007B 178 | #define PRODUCT_CLOUD_HOST_INFRASTRUCTURE_SERVER 0x0000007C 179 | #define PRODUCT_ENTERPRISE_S 0x0000007D 180 | #define PRODUCT_ENTERPRISE_S_N 0x0000007E 181 | #define PRODUCT_PROFESSIONAL_S 0x0000007F 182 | #define PRODUCT_PROFESSIONAL_S_N 0x00000080 183 | #define PRODUCT_ENTERPRISE_S_EVALUATION 0x00000081 184 | #define PRODUCT_ENTERPRISE_S_N_EVALUATION 0x00000082 185 | #define PRODUCT_HOLOGRAPHIC 0x00000087 186 | #define PRODUCT_HOLOGRAPHIC_BUSINESS 0x00000088 187 | #define PRODUCT_PRO_SINGLE_LANGUAGE 0x0000008A 188 | #define PRODUCT_PRO_CHINA 0x0000008B 189 | #define PRODUCT_ENTERPRISE_SUBSCRIPTION 0x0000008C 190 | #define PRODUCT_ENTERPRISE_SUBSCRIPTION_N 0x0000008D 191 | #define PRODUCT_DATACENTER_NANO_SERVER 0x0000008F 192 | #define PRODUCT_STANDARD_NANO_SERVER 0x00000090 193 | #define PRODUCT_DATACENTER_A_SERVER_CORE 0x00000091 194 | #define PRODUCT_STANDARD_A_SERVER_CORE 0x00000092 195 | #define PRODUCT_DATACENTER_WS_SERVER_CORE 0x00000093 196 | #define PRODUCT_STANDARD_WS_SERVER_CORE 0x00000094 197 | #define PRODUCT_UTILITY_VM 0x00000095 198 | #define PRODUCT_DATACENTER_EVALUATION_SERVER_CORE 0x0000009F 199 | #define PRODUCT_STANDARD_EVALUATION_SERVER_CORE 0x000000A0 200 | #define PRODUCT_PRO_WORKSTATION 0x000000A1 201 | #define PRODUCT_PRO_WORKSTATION_N 0x000000A2 202 | #define PRODUCT_PRO_FOR_EDUCATION 0x000000A4 203 | #define PRODUCT_PRO_FOR_EDUCATION_N 0x000000A5 204 | #define PRODUCT_AZURE_SERVER_CORE 0x000000A8 205 | #define PRODUCT_AZURE_NANO_SERVER 0x000000A9 206 | #define PRODUCT_ENTERPRISEG 0x000000AB 207 | #define PRODUCT_ENTERPRISEGN 0x000000AC 208 | #define PRODUCT_SERVERRDSH 0x000000AF 209 | #define PRODUCT_CLOUD 0x000000B2 210 | #define PRODUCT_CLOUDN 0x000000B3 211 | #define PRODUCT_HUBOS 0x000000B4 212 | #define PRODUCT_ONECOREUPDATEOS 0x000000B6 213 | #define PRODUCT_CLOUDE 0x000000B7 214 | #define PRODUCT_IOTOS 0x000000B9 215 | #define PRODUCT_CLOUDEN 0x000000BA 216 | #define PRODUCT_IOTEDGEOS 0x000000BB 217 | #define PRODUCT_IOTENTERPRISE 0x000000BC 218 | #define PRODUCT_LITE 0x000000BD 219 | #define PRODUCT_IOTENTERPRISES 0x000000BF 220 | #define PRODUCT_XBOX_SYSTEMOS 0x000000C0 221 | #define PRODUCT_XBOX_GAMEOS 0x000000C2 222 | #define PRODUCT_XBOX_ERAOS 0x000000C3 223 | #define PRODUCT_XBOX_DURANGOHOSTOS 0x000000C4 224 | #define PRODUCT_XBOX_SCARLETTHOSTOS 0x000000C5 225 | #define PRODUCT_XBOX_KEYSTONE 0x000000C6 226 | #define PRODUCT_AZURE_SERVER_CLOUDHOST 0x000000C7 227 | #define PRODUCT_AZURE_SERVER_CLOUDMOS 0x000000C8 228 | #define PRODUCT_CLOUDEDITIONN 0x000000CA 229 | #define PRODUCT_CLOUDEDITION 0x000000CB 230 | #define PRODUCT_AZURESTACKHCI_SERVER_CORE 0x00000196 231 | #define PRODUCT_DATACENTER_SERVER_AZURE_EDITION 0x00000197 232 | #define PRODUCT_DATACENTER_SERVER_CORE_AZURE_EDITION 0x00000198 233 | 234 | #define PRODUCT_UNLICENSED 0xABCDABCD 235 | 236 | // ChatGPT... 237 | #define PRODUCT_ENTERPRISE_G 0x00000067 238 | #define PRODUCT_PROFESSIONAL_WORKSTATION 0x000000B5 239 | #define PRODUCT_PROFESSIONAL_WORKSTATION_N 0x000000B6 240 | 241 | #define SM_TABLETPC 86 242 | #define SM_MEDIACENTER 87 243 | #define SM_STARTER 88 244 | #define SM_SERVERR2 89 245 | -------------------------------------------------------------------------------- /libcdi/Priscilla/UtilityFx.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*/ 2 | // Author : hiyohiyo 3 | // Mail : hiyohiyo@crystalmark.info 4 | // Web : https://crystalmark.info/ 5 | // License : MIT License 6 | /*---------------------------------------------------------------------------*/ 7 | 8 | #include "../stdafx.h" 9 | #include "UtilityFx.h" 10 | 11 | #include 12 | #pragma comment(lib,"version.lib") 13 | 14 | ////------------------------------------------------ 15 | // Debug 16 | ////------------------------------------------------ 17 | 18 | static const DWORD DEBUG_MODE_NONE = 0; 19 | static const DWORD DEBUG_MODE_LOG = 1; 20 | static const DWORD DEBUG_MODE_MESSAGE = 2; 21 | 22 | static DWORD debugMode = DEBUG_MODE_NONE; 23 | 24 | void SetDebugMode(DWORD mode) 25 | { 26 | if (mode <= DEBUG_MODE_MESSAGE) 27 | { 28 | debugMode = mode; 29 | } 30 | else 31 | { 32 | debugMode = DEBUG_MODE_NONE; 33 | } 34 | } 35 | 36 | void DebugPrint(CString cstr) 37 | { 38 | static BOOL flag = TRUE; 39 | static TCHAR file[MAX_PATH] = _T(""); 40 | static DWORD first = (DWORD)GetTickCountFx(); 41 | CString output; 42 | 43 | output.Format(_T("%08d "), (DWORD)GetTickCountFx() - first); 44 | output += cstr; 45 | output.Append(_T("\n")); 46 | output.Replace(_T("\r"), _T("")); 47 | 48 | if (flag) 49 | { 50 | TCHAR* ptrEnd; 51 | ::GetModuleFileName(NULL, file, MAX_PATH); 52 | if ((ptrEnd = _tcsrchr(file, '.')) != NULL) 53 | { 54 | *ptrEnd = '\0'; 55 | #if _MSC_VER <= 1310 56 | _tcscat(file, _T(".log")); 57 | #else 58 | _tcscat_s(file, MAX_PATH, _T(".log")); 59 | #endif 60 | } 61 | DeleteFile(file); 62 | flag = FALSE; 63 | } 64 | 65 | if (debugMode == DEBUG_MODE_NONE) 66 | { 67 | return; 68 | } 69 | 70 | FILE* fp = NULL; 71 | #if _MSC_VER <= 1310 72 | fp = _tfopen(file, _T("ac")); 73 | #else 74 | _tfopen_s(&fp, file, _T("ac")); 75 | #endif 76 | 77 | if (fp != NULL) 78 | { 79 | _ftprintf(fp, _T("%s"), (LPCTSTR)output); 80 | fflush(fp); 81 | fclose(fp); 82 | } 83 | 84 | if (debugMode == DEBUG_MODE_MESSAGE) 85 | { 86 | AfxMessageBox(output); 87 | } 88 | } 89 | 90 | ////------------------------------------------------ 91 | // File Information 92 | ////------------------------------------------------ 93 | 94 | int GetFileVersion(const TCHAR* file, TCHAR* version) 95 | { 96 | ULONG reserved = 0; 97 | VS_FIXEDFILEINFO vffi = { 0 }; 98 | TCHAR* buf = NULL; 99 | int Locale = 0; 100 | TCHAR str[256] = { 0 }; 101 | 102 | UINT size = GetFileVersionInfoSize((TCHAR*)file, &reserved); 103 | TCHAR* vbuf = new TCHAR[size]; 104 | if (GetFileVersionInfo((TCHAR*)file, 0, size, vbuf)) 105 | { 106 | VerQueryValue(vbuf, _T("\\"), (void**)&buf, &size); 107 | CopyMemory(&vffi, buf, sizeof(VS_FIXEDFILEINFO)); 108 | 109 | VerQueryValue(vbuf, _T("\\VarFileInfo\\Translation"), (void**)&buf, &size); 110 | CopyMemory(&Locale, buf, sizeof(int)); 111 | wsprintf(str, _T("\\StringFileInfo\\%04X%04X\\%s"), 112 | LOWORD(Locale), HIWORD(Locale), _T("FileVersion")); 113 | VerQueryValue(vbuf, str, (void**)&buf, &size); 114 | 115 | #if _MSC_VER <= 1310 116 | _tcscpy(str, buf); 117 | #else 118 | _tcscpy_s(str, 256, buf); 119 | #endif 120 | 121 | if (version != NULL) 122 | { 123 | #if _MSC_VER <= 1310 124 | _tcscpy(version,buf); 125 | #else 126 | _tcscpy_s(version, 256, buf); 127 | #endif 128 | } 129 | } 130 | delete[] vbuf; 131 | 132 | if (_tcscmp(str, _T("")) != 0) 133 | { 134 | return int(_tstof(str) * 100); 135 | } 136 | else 137 | { 138 | return 0; 139 | } 140 | } 141 | 142 | void GetFileVersionEx(const TCHAR* file, CString& version) 143 | { 144 | ULONG reserved = 0; 145 | VS_FIXEDFILEINFO vffi = { 0 }; 146 | TCHAR* buf = NULL; 147 | int Locale = 0; 148 | TCHAR str[256] = { 0 }; 149 | 150 | UINT size = GetFileVersionInfoSize((TCHAR*)file, &reserved); 151 | TCHAR* vbuf = new TCHAR[size]; 152 | if (GetFileVersionInfo((TCHAR*)file, 0, size, vbuf)) 153 | { 154 | VerQueryValue(vbuf, _T("\\"), (void**)&buf, &size); 155 | CopyMemory(&vffi, buf, sizeof(VS_FIXEDFILEINFO)); 156 | 157 | if (vffi.dwSignature == 0xfeef04bd) 158 | { 159 | version.Format(_T("%d.%d.%d.%d"), 160 | HIWORD(vffi.dwFileVersionMS), 161 | LOWORD(vffi.dwFileVersionMS), 162 | HIWORD(vffi.dwFileVersionLS), 163 | LOWORD(vffi.dwFileVersionLS)); 164 | } 165 | } 166 | delete[] vbuf; 167 | } 168 | 169 | BOOL IsFileExist(const TCHAR* path) 170 | { 171 | FILE* fp = NULL; 172 | 173 | #if _MSC_VER <= 1310 174 | fp = _tfopen(path, _T("rb")); 175 | if (fp == NULL) 176 | #else 177 | errno_t err = 0; 178 | err = _tfopen_s(&fp, path, _T("rb")); 179 | if (err != 0 || fp == NULL) 180 | #endif 181 | { 182 | return FALSE; 183 | } 184 | fclose(fp); 185 | return TRUE; 186 | } 187 | 188 | BOOL CanWriteFile(const TCHAR* path) 189 | { 190 | HANDLE hFile = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL); 191 | 192 | if (hFile == INVALID_HANDLE_VALUE) { return FALSE; } 193 | const char* testData = "1"; 194 | DWORD bytesWritten; 195 | BOOL writeResult = WriteFile(hFile, testData, (DWORD)strlen(testData), &bytesWritten, NULL); 196 | CloseHandle(hFile); 197 | 198 | return writeResult; 199 | } 200 | 201 | 202 | ////------------------------------------------------ 203 | // Utility 204 | ////------------------------------------------------ 205 | 206 | typedef ULONGLONG(WINAPI* FuncGetTickCount64)(); 207 | 208 | ULONGLONG GetTickCountFx() 209 | { 210 | HMODULE hModule = GetModuleHandle(_T("kernel32.dll")); 211 | FuncGetTickCount64 pGetTickCount64 = NULL; 212 | if (hModule) 213 | { 214 | pGetTickCount64 = (FuncGetTickCount64)GetProcAddress(hModule, "GetTickCount64"); 215 | } 216 | 217 | if (pGetTickCount64) 218 | { 219 | return (ULONGLONG)pGetTickCount64(); 220 | } 221 | else 222 | { 223 | #if _MSC_VER <= 1310 224 | return (ULONGLONG)GetTickCount(); 225 | #else 226 | return _Pragma("warning(suppress: 28159)") (ULONGLONG)GetTickCount(); 227 | #endif 228 | } 229 | } 230 | 231 | ULONG64 B8toB64(BYTE b0, BYTE b1, BYTE b2, BYTE b3, BYTE b4, BYTE b5, BYTE b6, BYTE b7) 232 | { 233 | ULONG64 data = 234 | ((ULONG64)b7 << 56) 235 | + ((ULONG64)b6 << 48) 236 | + ((ULONG64)b5 << 40) 237 | + ((ULONG64)b4 << 32) 238 | + ((ULONG64)b3 << 24) 239 | + ((ULONG64)b2 << 16) 240 | + ((ULONG64)b1 << 8) 241 | + ((ULONG64)b0 << 0); 242 | 243 | return data; 244 | } 245 | 246 | DWORD B8toB32(BYTE b0, BYTE b1, BYTE b2, BYTE b3) 247 | { 248 | DWORD data = 249 | ((DWORD)b3 << 24) 250 | + ((DWORD)b2 << 16) 251 | + ((DWORD)b1 << 8) 252 | + ((DWORD)b0 << 0); 253 | 254 | return data; 255 | } 256 | 257 | void SplitCString(const CString& str, const CString& delimiter, CStringArray& arr) 258 | { 259 | int startPos = 0; 260 | while (startPos >= 0) 261 | { 262 | int endPos = str.Find(delimiter, startPos); 263 | if (endPos == -1) 264 | { 265 | arr.Add(str.Mid(startPos)); 266 | break; 267 | } 268 | arr.Add(str.Mid(startPos, endPos - startPos)); 269 | startPos = endPos + lstrlen(delimiter); 270 | } 271 | } 272 | 273 | ////------------------------------------------------ 274 | // .ini support function 275 | ////------------------------------------------------ 276 | 277 | DWORD GetPrivateProfileStringFx(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpDefault, LPTSTR lpReturnedString, DWORD nSize, LPCTSTR lpFileName) 278 | { 279 | DWORD result = 0; 280 | CString key = lpKeyName; 281 | key.Replace(_T("="), _T("%#3D")); 282 | key.Replace(_T("\""), _T("%#22")); 283 | result = GetPrivateProfileString(lpAppName, key, lpDefault, lpReturnedString, nSize, lpFileName); 284 | 285 | CString value = lpReturnedString; 286 | value.Replace(_T("%#3D"), _T("=")); 287 | value.Replace(_T("%#22"), _T("\"")); 288 | 289 | #if _MSC_VER <= 1310 290 | _tcscpy(lpReturnedString, (LPCTSTR)value); 291 | #else 292 | _tcscpy_s(lpReturnedString, nSize, (LPCTSTR)value); 293 | #endif 294 | 295 | return result; 296 | } 297 | 298 | UINT GetPrivateProfileIntFx(LPCTSTR lpAppName, LPCTSTR lpKeyName, INT nDefault, LPCTSTR lpFileName) 299 | { 300 | CString key = lpKeyName; 301 | key.Replace(_T("="), _T("%#3D")); 302 | key.Replace(_T("\""), _T("%#22")); 303 | 304 | return GetPrivateProfileInt(lpAppName, key, nDefault, lpFileName); 305 | } 306 | 307 | BOOL WritePrivateProfileStringFx(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpString, LPCTSTR lpFileName) 308 | { 309 | CString key = lpKeyName; 310 | key.Replace(_T("="), _T("%#3D")); 311 | key.Replace(_T("\""), _T("%#22")); 312 | 313 | CString value = lpString; 314 | value.Replace(_T("="), _T("%#3D")); 315 | value.Replace(_T("\""), _T("%#22")); 316 | 317 | value = _T("\"" + value + _T("\"")); 318 | 319 | return WritePrivateProfileString(lpAppName, key, value, lpFileName); 320 | } 321 | 322 | ////------------------------------------------------ 323 | // Check CodeSign 324 | ////------------------------------------------------ 325 | #if _MSC_VER > 1310 326 | #include 327 | #pragma comment(lib, "Wintrust.lib") 328 | #pragma comment(lib, "Crypt32.lib") 329 | 330 | BOOL CheckCodeSign(LPCWSTR certName, LPCWSTR filePath) 331 | { 332 | #ifdef _DEBUG 333 | return TRUE; 334 | #endif 335 | 336 | // check sign 337 | 338 | WINTRUST_FILE_INFO FileData = { sizeof(WINTRUST_FILE_INFO) }; 339 | FileData.pcwszFilePath = filePath; 340 | 341 | GUID WVTPolicyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2; 342 | WINTRUST_DATA WinTrustData = { sizeof(WinTrustData) }; 343 | WinTrustData.dwUIChoice = WTD_UI_NONE; 344 | WinTrustData.fdwRevocationChecks = WTD_REVOKE_NONE; 345 | WinTrustData.dwUnionChoice = WTD_CHOICE_FILE; 346 | WinTrustData.dwStateAction = WTD_STATEACTION_VERIFY; 347 | WinTrustData.pFile = &FileData; 348 | 349 | const LONG ret = WinVerifyTrust(NULL, &WVTPolicyGUID, &WinTrustData); 350 | 351 | bool cert_chk = false; 352 | 353 | if (ret == ERROR_SUCCESS) { 354 | // retreive the signer certificate and display its information 355 | CRYPT_PROVIDER_DATA const* psProvData = NULL; 356 | CRYPT_PROVIDER_SGNR* psProvSigner = NULL; 357 | CRYPT_PROVIDER_CERT* psProvCert = NULL; 358 | 359 | psProvData = WTHelperProvDataFromStateData(WinTrustData.hWVTStateData); 360 | if (psProvData) { 361 | psProvSigner = WTHelperGetProvSignerFromChain((PCRYPT_PROVIDER_DATA)psProvData, 0, FALSE, 0); 362 | if (psProvSigner) { 363 | psProvCert = WTHelperGetProvCertFromChain(psProvSigner, 0); 364 | if (psProvCert) { 365 | wchar_t szCertName[200] = {0}; 366 | DWORD dwStrType = CERT_X500_NAME_STR; 367 | CertGetNameStringW(psProvCert->pCert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, &dwStrType, szCertName, 200); 368 | cert_chk = !(szCertName[0] == '\0' || wcscmp(szCertName, certName) != 0); 369 | } 370 | } 371 | } 372 | } 373 | WinTrustData.dwStateAction = WTD_STATEACTION_CLOSE; 374 | (void)WinVerifyTrust(NULL, &WVTPolicyGUID, &WinTrustData); 375 | if (!cert_chk) return FALSE; 376 | 377 | return TRUE; 378 | } 379 | #endif 380 | 381 | ////------------------------------------------------ 382 | // Play Sound 383 | ////------------------------------------------------ 384 | 385 | #include 386 | #include "digitalv.h" 387 | 388 | #pragma comment(lib, "winmm.lib") 389 | 390 | /* 391 | void ShowMciError(DWORD error) 392 | { 393 | TCHAR errorBuf[MAXERRORLENGTH]; 394 | 395 | if (mciGetErrorString(error, (LPTSTR)errorBuf, MAXERRORLENGTH)) 396 | { 397 | AfxMessageBox(errorBuf); 398 | } 399 | else 400 | { 401 | AfxMessageBox(_T("Unknown Error"); 402 | } 403 | } 404 | */ 405 | 406 | BOOL AlertSound(const CString& alertSoundPath, int volume) 407 | { 408 | #if _MSC_VER <= 1310 409 | PlaySound(alertSoundPath, NULL, SND_SYNC); 410 | #else 411 | 412 | static MCI_OPEN_PARMS mop = { 0 }; 413 | static MCI_PLAY_PARMS mpp = { 0 }; 414 | static MCI_GENERIC_PARMS mgp = { 0 }; 415 | MCIERROR error = 0; 416 | 417 | if (mop.wDeviceID != 0) 418 | { 419 | // Stop and close 420 | error = mciSendCommandW(mop.wDeviceID, MCI_STOP, 0, 0); 421 | error = mciSendCommandW(mop.wDeviceID, MCI_CLOSE, 0, 0); 422 | mop.wDeviceID = 0; 423 | ZeroMemory(&mop, sizeof(MCI_OPEN_PARMS)); 424 | if (error) 425 | { 426 | // ShowMciError(error); 427 | return FALSE; 428 | } 429 | } 430 | 431 | if (alertSoundPath.Compare(_T("")) == 0) { 432 | // Close 433 | error = mciSendCommandW(mop.wDeviceID, MCI_CLOSE, 0, 0); 434 | if (error) 435 | { 436 | // ShowMciError(error); 437 | return FALSE; 438 | } 439 | return TRUE; 440 | } 441 | 442 | // Open 443 | mop.lpstrElementName = (LPCTSTR)alertSoundPath; 444 | mop.lpstrDeviceType = _T("MPEGVideo"); 445 | error = mciSendCommandW(NULL, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_ELEMENT, (DWORD_PTR)(&mop)); 446 | 447 | if (error) 448 | { 449 | // ShowMciError(error); 450 | return FALSE; 451 | } 452 | 453 | // Set volume 454 | if (volume < 0 || volume > 100) { volume = 80; } 455 | 456 | MCI_DGV_SETAUDIO_PARMS parms = { 0 }; 457 | parms.dwItem = MCI_DGV_SETAUDIO_VOLUME; 458 | parms.dwValue = volume * 10; // 0-1000 459 | error = mciSendCommand(mop.wDeviceID, MCI_SETAUDIO, MCI_DGV_SETAUDIO_ITEM | MCI_DGV_SETAUDIO_VALUE, (DWORD_PTR)&parms); 460 | if (error) 461 | { 462 | // ShowMciError(error); 463 | return FALSE; 464 | } 465 | // Seek 466 | error = mciSendCommand(mop.wDeviceID, MCI_SEEK, MCI_SEEK_TO_START, reinterpret_cast(&mgp)); 467 | if (error) 468 | { 469 | // ShowMciError(error); 470 | return FALSE; 471 | } 472 | 473 | // Play 474 | error = mciSendCommandW(mop.wDeviceID, MCI_PLAY, 0, reinterpret_cast(&mpp)); 475 | if (error) 476 | { 477 | // ShowMciError(error); 478 | return FALSE; 479 | } 480 | #endif 481 | 482 | return TRUE; 483 | } 484 | 485 | 486 | ////------------------------------------------------ 487 | // Hash 488 | ////------------------------------------------------ 489 | 490 | #if _MSC_VER > 1310 491 | #include 492 | #include 493 | #include 494 | #include 495 | #include 496 | CStringA MD5(const CStringA& str) 497 | { 498 | HCRYPTPROV hProv = 0; 499 | HCRYPTHASH hHash = 0; 500 | BYTE hash[16]; 501 | DWORD hashLen = 16; 502 | CStringA hashStr; 503 | 504 | if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { 505 | return ""; 506 | } 507 | 508 | if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) { 509 | CryptReleaseContext(hProv, 0); 510 | return ""; 511 | } 512 | 513 | std::string utf8Str(str); 514 | 515 | if (!CryptHashData(hHash, reinterpret_cast(utf8Str.c_str()), (DWORD)utf8Str.size(), 0)) { 516 | CryptDestroyHash(hHash); 517 | CryptReleaseContext(hProv, 0); 518 | return ""; 519 | } 520 | 521 | if (!CryptGetHashParam(hHash, HP_HASHVAL, hash, &hashLen, 0)) { 522 | CryptDestroyHash(hHash); 523 | CryptReleaseContext(hProv, 0); 524 | return ""; 525 | } 526 | 527 | for (DWORD i = 0; i < hashLen; ++i) { 528 | CString temp; 529 | temp.Format(_T("%02x"), hash[i]); 530 | hashStr += temp; 531 | } 532 | 533 | CryptDestroyHash(hHash); 534 | CryptReleaseContext(hProv, 0); 535 | 536 | return hashStr; 537 | } 538 | #else 539 | #include "md5.h" 540 | CStringA MD5(const CStringA& str) 541 | { 542 | char* input = (char*)(LPCSTR)str; 543 | uint8_t result[16] = { 0 }; 544 | md5String(input, result); 545 | 546 | CStringA hashStr; 547 | for (int i = 0; i < 16; ++i) 548 | { 549 | CStringA byteStr; 550 | byteStr.Format("%02x", result[i]); 551 | hashStr += byteStr; 552 | } 553 | 554 | return hashStr; 555 | } 556 | #endif 557 | 558 | ////------------------------------------------------ 559 | // Character Converter 560 | ////------------------------------------------------ 561 | 562 | CStringA URLEncode(const CStringA& str) 563 | { 564 | CStringA encoded; 565 | for (int i = 0; i < str.GetLength(); i++) 566 | { 567 | if (isalnum((BYTE)str[i]) || str[i] == '-' || str[i] == '_' || str[i] == '.' || str[i] == '~') 568 | { 569 | encoded += str[i]; 570 | } 571 | else 572 | { 573 | encoded.AppendFormat("%%%02X", (BYTE)str[i]); 574 | } 575 | } 576 | return encoded; 577 | } 578 | 579 | #if _MSC_VER <= 1310 580 | 581 | // https://github.com/roytam1/RetroZilla/commit/e44dd98dbf2effeff3305430835e889d76ec73b4#diff-065242b491de972d8519dbbae0c4c8dfb6a1a3c3eb8b9936d56a4c1ad63ec7abR126-R282 582 | /*** UTF16<-->UTF8 functions minicking MultiByteToWideChar/WideCharToMultiByte ***/ 583 | int utf8GetMaskIndex(unsigned char n) { 584 | if ((unsigned char)(n + 2) < 0xc2) return 1; // 00~10111111, fe, ff 585 | if (n < 0xe0) return 2; // 110xxxxx 586 | if (n < 0xf0) return 3; // 1110xxxx 587 | if (n < 0xf8) return 4; // 11110xxx 588 | if (n < 0xfc) return 5; // 111110xx 589 | return 6; // 1111110x 590 | } 591 | 592 | int wc2Utf8Len(wchar_t** n, int* len) { 593 | wchar_t* ch = *n, ch2; 594 | int qch; 595 | if ((0xD800 <= *ch && *ch <= 0xDBFF) && *len) { 596 | ch2 = *(ch + 1); 597 | if (0xDC00 <= ch2 && ch2 <= 0xDFFF) { 598 | qch = 0x10000 + (((*ch - 0xD800) & 0x3ff) << 10) + ((ch2 - 0xDC00) & 0x3ff); 599 | (*n)++; 600 | (*len)--; 601 | } 602 | } 603 | else 604 | qch = (int)*ch; 605 | 606 | if (qch <= 0x7f) return 1; 607 | else if (qch <= 0x7ff) return 2; 608 | else if (qch <= 0xffff) return 3; 609 | else if (qch <= 0x1fffff) return 4; 610 | else if (qch <= 0x3ffffff) return 5; 611 | else return 6; 612 | } 613 | 614 | int Utf8ToWideChar(unsigned int unused1, unsigned long unused2, char* sb, int ss, wchar_t* wb, int ws) { 615 | static const unsigned char utf8mask[] = { 0, 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; 616 | char* p = (char*)(sb); 617 | char* e = (char*)(sb + ss); 618 | wchar_t* w = wb; 619 | int cnt = 0, t, qch; 620 | 621 | if (ss < 1) { 622 | ss = lstrlenA(sb); 623 | e = (char*)(sb + ss); 624 | } 625 | 626 | if (wb && ws) { 627 | for (; p < e; ++w) { 628 | t = utf8GetMaskIndex(*p); 629 | qch = (*p++ & utf8mask[t]); 630 | while (p < e && --t) 631 | qch <<= 6, qch |= (*p++) & 0x3f; 632 | if (qch < 0x10000) { 633 | if (cnt <= ws) 634 | *w = (wchar_t)qch; 635 | cnt++; 636 | } 637 | else { 638 | if (cnt + 2 <= ws) { 639 | *w++ = (wchar_t)(0xD800 + (((qch - 0x10000) >> 10) & 0x3ff)), 640 | *w = (wchar_t)(0xDC00 + (((qch - 0x10000)) & 0x3ff)); 641 | } 642 | cnt += 2; 643 | } 644 | } 645 | if (cnt < ws) { 646 | *(wb + cnt) = 0; 647 | return cnt; 648 | } 649 | else { 650 | *(wb + ws) = 0; 651 | return ws; 652 | } 653 | } 654 | else { 655 | for (t; p < e;) { 656 | t = utf8GetMaskIndex(*p); 657 | qch = (*p++ & utf8mask[t]); 658 | while (p < e && --t) 659 | qch <<= 6, qch |= (*p++) & 0x3f; 660 | if (qch < 0x10000) 661 | cnt++; 662 | else 663 | cnt += 2; 664 | } 665 | return cnt + 1; 666 | } 667 | } 668 | 669 | int WideCharToUtf8(unsigned int unused1, unsigned long unused2, wchar_t* wb, int ws, char* sb, int ss) { 670 | wchar_t* p = (wchar_t*)(wb); 671 | wchar_t* e = (wchar_t*)(wb + ws); 672 | wchar_t* oldp; 673 | char* s = sb; 674 | int cnt = 0, qch, t; 675 | 676 | if (ws < 1) { 677 | ws = lstrlenW(wb); 678 | e = (wchar_t*)(wb + ws); 679 | } 680 | 681 | if (sb && ss) { 682 | for (t; p < e; ++p) { 683 | oldp = p; 684 | t = wc2Utf8Len(&p, &ws); 685 | 686 | if (p != oldp) { /* unicode surrogates encountered */ 687 | qch = 0x10000 + (((*oldp - 0xD800) & 0x3ff) << 10) + ((*p - 0xDC00) & 0x3ff); 688 | } 689 | else 690 | qch = *p; 691 | 692 | if (qch <= 0x7f) 693 | *s++ = (char)(qch), 694 | cnt++; 695 | else if (qch <= 0x7ff) 696 | *s++ = 0xc0 | (char)(qch >> 6), 697 | *s++ = 0x80 | (char)(qch & 0x3f), 698 | cnt += 2; 699 | else if (qch <= 0xffff) 700 | *s++ = 0xe0 | (char)(qch >> 12), 701 | *s++ = 0x80 | (char)((qch >> 6) & 0x3f), 702 | *s++ = 0x80 | (char)(qch & 0x3f), 703 | cnt += 3; 704 | else if (qch <= 0x1fffff) 705 | *s++ = 0xf0 | (char)(qch >> 18), 706 | *s++ = 0x80 | (char)((qch >> 12) & 0x3f), 707 | *s++ = 0x80 | (char)((qch >> 6) & 0x3f), 708 | *s++ = 0x80 | (char)(qch & 0x3f), 709 | cnt += 4; 710 | else if (qch <= 0x3ffffff) 711 | *s++ = 0xf8 | (char)(qch >> 24), 712 | *s++ = 0x80 | (char)((qch >> 18) & 0x3f), 713 | *s++ = 0x80 | (char)((qch >> 12) & 0x3f), 714 | *s++ = 0x80 | (char)((qch >> 6) & 0x3f), 715 | *s++ = 0x80 | (char)(qch & 0x3f), 716 | cnt += 5; 717 | else 718 | *s++ = 0xfc | (char)(qch >> 30), 719 | *s++ = 0x80 | (char)((qch >> 24) & 0x3f), 720 | *s++ = 0x80 | (char)((qch >> 18) & 0x3f), 721 | *s++ = 0x80 | (char)((qch >> 12) & 0x3f), 722 | *s++ = 0x80 | (char)((qch >> 6) & 0x3f), 723 | *s++ = 0x80 | (char)(qch & 0x3f), 724 | cnt += 6; 725 | } 726 | if (cnt < ss) { 727 | *(sb + cnt) = 0; 728 | return cnt; 729 | } 730 | else { 731 | *(sb + ss) = 0; 732 | return ss; 733 | } 734 | } 735 | else { 736 | for (t; p < e; ++p) { 737 | t = wc2Utf8Len(&p, &ws); 738 | cnt += t; 739 | } 740 | return cnt + 1; 741 | } 742 | } 743 | /*** Ends ***/ 744 | 745 | #ifdef UNICODE 746 | CStringA UTF16toUTF8(const CStringW& utf16str) 747 | { 748 | if (IsNT3() || IsNT4()) 749 | { 750 | CStringA utf8str; 751 | WCHAR* utf16string = new WCHAR[(utf16str.GetLength() + 1) * 2]; 752 | wsprintf(utf16string, L"%s", utf16str); 753 | int utf16Length = utf16str.GetLength(); 754 | int utf8Length = WideCharToUtf8(CP_UTF8, 0, utf16string, -1, NULL, 0); 755 | if (utf8Length <= 0) { return ""; } 756 | WideCharToUtf8(CP_UTF8, 0, utf16string, -1, utf8str.GetBuffer(utf8Length), utf8Length); 757 | utf8str.ReleaseBuffer(); 758 | delete utf16string; 759 | return utf8str; 760 | } 761 | else 762 | { 763 | CStringA utf8str; 764 | int utf8Length = WideCharToMultiByte(CP_UTF8, 0, utf16str, -1, NULL, 0, NULL, NULL); 765 | if (utf8Length <= 0) { return ""; } 766 | WideCharToMultiByte(CP_UTF8, 0, utf16str, -1, utf8str.GetBuffer(utf8Length), utf8Length, NULL, NULL); 767 | utf8str.ReleaseBuffer(); 768 | return utf8str; 769 | } 770 | } 771 | 772 | CStringW UTF8toUTF16(const CStringA& utf8str) 773 | { 774 | CStringW utf16str; 775 | CHAR* utf8string = new CHAR[(utf8str.GetLength() + 1) * 2]; 776 | sprintf(utf8string, "%s", utf8str); 777 | int utf8Length = utf8str.GetLength(); 778 | int utf16Length = Utf8ToWideChar(1200, 0, utf8string, -1, NULL, 0); 779 | if (utf16Length <= 0) { return L""; } 780 | Utf8ToWideChar(1200, 0, utf8string, -1, utf16str.GetBuffer(utf16Length), utf16Length); 781 | utf16str.ReleaseBuffer(); 782 | delete utf8string; 783 | return utf16str; 784 | } 785 | 786 | #else 787 | CStringA ANSItoUTF8(const CStringA& ansiStr) 788 | { 789 | int utf16Length = MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, NULL, 0); 790 | if (utf16Length <= 0) { return ""; } 791 | CStringW utf16str; 792 | MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, utf16str.GetBuffer(utf16Length), utf16Length); 793 | utf16str.ReleaseBuffer(); 794 | 795 | CStringA utf8str; 796 | int utf8Length = WideCharToUtf8(CP_UTF8, 0, utf16str.GetBuffer(utf16Length), -1, NULL, 0); 797 | if (utf8Length <= 0) { return ""; } 798 | WideCharToUtf8(CP_UTF8, 0, utf16str.GetBuffer(utf16Length), -1, utf8str.GetBuffer(utf8Length), utf8Length); 799 | utf8str.ReleaseBuffer(); 800 | return utf8str; 801 | } 802 | #endif 803 | #else 804 | 805 | CStringA UTF16toUTF8(const CStringW& utf16str) 806 | { 807 | CStringA utf8str(CW2A(utf16str, CP_UTF8)); 808 | return utf8str; 809 | } 810 | 811 | CStringW UTF8toUTF16(const CStringA& utf8str) 812 | { 813 | CStringW utf16str; 814 | utf16str = CA2W(utf8str); 815 | return utf16str; 816 | } 817 | #endif 818 | 819 | #ifdef UNICODE 820 | CStringA UE(const CStringW& utf16str) 821 | { 822 | return URLEncode(UTF16toUTF8(utf16str)); 823 | } 824 | #else 825 | CStringA UE(const CStringA& ansiStr) 826 | { 827 | return URLEncode(ANSItoUTF8(ansiStr)); 828 | } 829 | #endif 830 | ////------------------------------------------------ 831 | // Clipboard 832 | ////------------------------------------------------ 833 | 834 | void SetClipboardText(CString clip) 835 | { 836 | if (OpenClipboard(NULL)) 837 | { 838 | HGLOBAL clipbuffer; 839 | TCHAR* buffer = NULL; 840 | EmptyClipboard(); 841 | clipbuffer = GlobalAlloc(GMEM_DDESHARE, sizeof(TCHAR) * (clip.GetLength() + 1)); 842 | if (clipbuffer != NULL) 843 | { 844 | buffer = (TCHAR*)GlobalLock(clipbuffer); 845 | if (buffer != NULL) 846 | { 847 | #if _MSC_VER <= 1310 848 | _tcscpy(buffer, LPCTSTR(clip)); 849 | #else 850 | _tcscpy_s(buffer, clip.GetLength() + 1, LPCTSTR(clip)); 851 | #endif 852 | } 853 | GlobalUnlock(clipbuffer); 854 | #ifdef UNICODE 855 | SetClipboardData(CF_UNICODETEXT, clipbuffer); 856 | #else 857 | SetClipboardData(CF_TEXT, clipbuffer); 858 | #endif 859 | } 860 | CloseClipboard(); 861 | } 862 | } 863 | -------------------------------------------------------------------------------- /libcdi/Priscilla/UtilityFx.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*/ 2 | // Author : hiyohiyo 3 | // Mail : hiyohiyo@crystalmark.info 4 | // Web : https://crystalmark.info/ 5 | // License : MIT License 6 | /*---------------------------------------------------------------------------*/ 7 | 8 | #pragma once 9 | 10 | ////------------------------------------------------ 11 | // Debug 12 | ////------------------------------------------------ 13 | 14 | void SetDebugMode(DWORD mode); 15 | void DebugPrint(CString cstr); 16 | 17 | ////------------------------------------------------ 18 | // File Information 19 | ////------------------------------------------------ 20 | 21 | int GetFileVersion(const TCHAR* fileName, TCHAR* version = NULL); 22 | void GetFileVersionEx(const TCHAR* file, CString& version); 23 | BOOL IsFileExist(const TCHAR* fileName); 24 | BOOL CanWriteFile(const TCHAR* fileName); 25 | 26 | ////------------------------------------------------ 27 | // Utility 28 | ////------------------------------------------------ 29 | 30 | ULONGLONG GetTickCountFx(); 31 | 32 | ULONG64 B8toB64(BYTE b0, BYTE b1 = 0, BYTE b2 = 0, BYTE b3 = 0, BYTE b4 = 0, BYTE b5 = 0, BYTE b6 = 0, BYTE b7 = 0); 33 | DWORD B8toB32(BYTE b0, BYTE b1 = 0, BYTE b2 = 0, BYTE b3 = 0); 34 | void SplitCString(const CString& str, const CString& delimiter, CStringArray& arr); 35 | 36 | ////------------------------------------------------ 37 | // .ini support function 38 | ////------------------------------------------------ 39 | 40 | DWORD GetPrivateProfileStringFx(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpDefault, LPTSTR lpReturnedString,DWORD nSize,LPCTSTR lpFileName); 41 | UINT GetPrivateProfileIntFx(LPCTSTR lpAppName, LPCTSTR lpKeyName, INT nDefault, LPCTSTR lpFileName); 42 | BOOL WritePrivateProfileStringFx(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpString, LPCTSTR lpFileName); 43 | 44 | ////------------------------------------------------ 45 | // Check CodeSign 46 | ////------------------------------------------------ 47 | 48 | #if _MSC_VER > 1310 49 | BOOL CheckCodeSign(LPCWSTR certName, LPCWSTR filePath); 50 | #endif 51 | 52 | ////------------------------------------------------ 53 | // Play Sound 54 | ////------------------------------------------------ 55 | 56 | BOOL AlertSound(const CString& alertSoundPath, int volume); 57 | 58 | ////------------------------------------------------ 59 | // Hash 60 | ////------------------------------------------------ 61 | 62 | CStringA MD5(const CStringA& str); 63 | 64 | ////------------------------------------------------ 65 | // Character Converter 66 | ////------------------------------------------------ 67 | 68 | CStringW UTF8toUTF16(const CStringA& utf8str); 69 | CStringA UTF16toUTF8(const CStringW& utf16str); 70 | CStringA URLEncode(const CStringA& str); 71 | CStringA UE(const CStringW& utf16str); 72 | CStringA UE(const CStringA& ansiStr); 73 | 74 | ////------------------------------------------------ 75 | // Clipboard 76 | ////------------------------------------------------ 77 | 78 | void SetClipboardText(CString clip); -------------------------------------------------------------------------------- /libcdi/Priscilla/md5.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm 3 | * and modified slightly to be functionally identical but condensed into control structures. 4 | */ 5 | 6 | #include "../stdafx.h" 7 | #include "md5.h" 8 | 9 | #if _MSC_VER > 1310 10 | 11 | // skip 12 | 13 | #else 14 | 15 | /* 16 | * Constants defined by the MD5 algorithm 17 | */ 18 | #define A 0x67452301 19 | #define B 0xefcdab89 20 | #define C 0x98badcfe 21 | #define D 0x10325476 22 | 23 | static uint32_t S[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 24 | 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 25 | 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 26 | 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21}; 27 | 28 | static uint32_t K[] = {0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 29 | 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 30 | 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 31 | 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 32 | 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 33 | 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 34 | 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 35 | 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 36 | 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 37 | 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 38 | 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 39 | 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 40 | 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 41 | 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 42 | 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 43 | 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391}; 44 | 45 | /* 46 | * Padding used to make the size (in bits) of the input congruent to 448 mod 512 47 | */ 48 | static uint8_t PADDING[] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 49 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 50 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 51 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 52 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 53 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 54 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 55 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 56 | 57 | /* 58 | * Bit-manipulation functions defined by the MD5 algorithm 59 | */ 60 | #define F(X, Y, Z) ((X & Y) | (~X & Z)) 61 | #define G(X, Y, Z) ((X & Z) | (Y & ~Z)) 62 | #define H(X, Y, Z) (X ^ Y ^ Z) 63 | #define I(X, Y, Z) (Y ^ (X | ~Z)) 64 | 65 | /* 66 | * Rotates a 32-bit word left by n bits 67 | */ 68 | uint32_t rotateLeft(uint32_t x, uint32_t n){ 69 | return (x << n) | (x >> (32 - n)); 70 | } 71 | 72 | 73 | /* 74 | * Initialize a context 75 | */ 76 | void md5Init(MD5Context *ctx){ 77 | ctx->size = (uint64_t)0; 78 | 79 | ctx->buffer[0] = (uint32_t)A; 80 | ctx->buffer[1] = (uint32_t)B; 81 | ctx->buffer[2] = (uint32_t)C; 82 | ctx->buffer[3] = (uint32_t)D; 83 | } 84 | 85 | /* 86 | * Add some amount of input to the context 87 | * 88 | * If the input fills out a block of 512 bits, apply the algorithm (md5Step) 89 | * and save the result in the buffer. Also updates the overall size. 90 | */ 91 | void md5Update(MD5Context *ctx, uint8_t *input_buffer, size_t input_len){ 92 | uint32_t input[16]; 93 | unsigned int offset = (unsigned int)(ctx->size % 64); 94 | ctx->size += (uint64_t)input_len; 95 | 96 | // Copy each byte in input_buffer into the next space in our context input 97 | for(unsigned int i = 0; i < input_len; ++i){ 98 | ctx->input[offset++] = (uint8_t)*(input_buffer + i); 99 | 100 | // If we've filled our context input, copy it into our local array input 101 | // then reset the offset to 0 and fill in a new buffer. 102 | // Every time we fill out a chunk, we run it through the algorithm 103 | // to enable some back and forth between cpu and i/o 104 | if(offset % 64 == 0){ 105 | for(unsigned int j = 0; j < 16; ++j){ 106 | // Convert to little-endian 107 | // The local variable `input` our 512-bit chunk separated into 32-bit words 108 | // we can use in calculations 109 | input[j] = (uint32_t)(ctx->input[(j * 4) + 3]) << 24 | 110 | (uint32_t)(ctx->input[(j * 4) + 2]) << 16 | 111 | (uint32_t)(ctx->input[(j * 4) + 1]) << 8 | 112 | (uint32_t)(ctx->input[(j * 4)]); 113 | } 114 | md5Step(ctx->buffer, input); 115 | offset = 0; 116 | } 117 | } 118 | } 119 | 120 | /* 121 | * Pad the current input to get to 448 bytes, append the size in bits to the very end, 122 | * and save the result of the final iteration into digest. 123 | */ 124 | void md5Finalize(MD5Context *ctx){ 125 | uint32_t input[16]; 126 | unsigned int offset = (unsigned int)(ctx->size % 64); 127 | unsigned int padding_length = offset < 56 ? 56 - offset : (56 + 64) - offset; 128 | 129 | // Fill in the padding and undo the changes to size that resulted from the update 130 | md5Update(ctx, PADDING, padding_length); 131 | ctx->size -= (uint64_t)padding_length; 132 | 133 | // Do a final update (internal to this function) 134 | // Last two 32-bit words are the two halves of the size (converted from bytes to bits) 135 | for(unsigned int j = 0; j < 14; ++j){ 136 | input[j] = (uint32_t)(ctx->input[(j * 4) + 3]) << 24 | 137 | (uint32_t)(ctx->input[(j * 4) + 2]) << 16 | 138 | (uint32_t)(ctx->input[(j * 4) + 1]) << 8 | 139 | (uint32_t)(ctx->input[(j * 4)]); 140 | } 141 | input[14] = (uint32_t)(ctx->size * 8); 142 | input[15] = (uint32_t)((ctx->size * 8) >> 32); 143 | 144 | md5Step(ctx->buffer, input); 145 | 146 | // Move the result into digest (convert from little-endian) 147 | for(unsigned int i = 0; i < 4; ++i){ 148 | ctx->digest[(i * 4) + 0] = (uint8_t)((ctx->buffer[i] & 0x000000FF)); 149 | ctx->digest[(i * 4) + 1] = (uint8_t)((ctx->buffer[i] & 0x0000FF00) >> 8); 150 | ctx->digest[(i * 4) + 2] = (uint8_t)((ctx->buffer[i] & 0x00FF0000) >> 16); 151 | ctx->digest[(i * 4) + 3] = (uint8_t)((ctx->buffer[i] & 0xFF000000) >> 24); 152 | } 153 | } 154 | 155 | /* 156 | * Step on 512 bits of input with the main MD5 algorithm. 157 | */ 158 | void md5Step(uint32_t *buffer, uint32_t *input){ 159 | uint32_t AA = buffer[0]; 160 | uint32_t BB = buffer[1]; 161 | uint32_t CC = buffer[2]; 162 | uint32_t DD = buffer[3]; 163 | 164 | uint32_t E; 165 | 166 | unsigned int j; 167 | 168 | for(unsigned int i = 0; i < 64; ++i){ 169 | switch(i / 16){ 170 | case 0: 171 | E = F(BB, CC, DD); 172 | j = i; 173 | break; 174 | case 1: 175 | E = G(BB, CC, DD); 176 | j = ((i * 5) + 1) % 16; 177 | break; 178 | case 2: 179 | E = H(BB, CC, DD); 180 | j = ((i * 3) + 5) % 16; 181 | break; 182 | default: 183 | E = I(BB, CC, DD); 184 | j = (i * 7) % 16; 185 | break; 186 | } 187 | 188 | uint32_t temp = DD; 189 | DD = CC; 190 | CC = BB; 191 | BB = BB + rotateLeft(AA + E + K[i] + input[j], S[i]); 192 | AA = temp; 193 | } 194 | 195 | buffer[0] += AA; 196 | buffer[1] += BB; 197 | buffer[2] += CC; 198 | buffer[3] += DD; 199 | } 200 | 201 | /* 202 | * Functions that run the algorithm on the provided input and put the digest into result. 203 | * result should be able to store 16 bytes. 204 | */ 205 | void md5String(char *input, uint8_t *result){ 206 | MD5Context ctx = {0}; 207 | md5Init(&ctx); 208 | md5Update(&ctx, (uint8_t *)input, strlen(input)); 209 | md5Finalize(&ctx); 210 | 211 | memcpy(result, ctx.digest, 16); 212 | } 213 | 214 | /* 215 | void md5File(FILE *file, uint8_t *result){ 216 | char *input_buffer = malloc(1024); 217 | size_t input_size = 0; 218 | 219 | MD5Context ctx; 220 | md5Init(&ctx); 221 | 222 | while((input_size = fread(input_buffer, 1, 1024, file)) > 0){ 223 | md5Update(&ctx, (uint8_t *)input_buffer, input_size); 224 | } 225 | 226 | md5Finalize(&ctx); 227 | 228 | free(input_buffer); 229 | 230 | memcpy(result, ctx.digest, 16); 231 | } 232 | */ 233 | 234 | #endif 235 | -------------------------------------------------------------------------------- /libcdi/Priscilla/md5.h: -------------------------------------------------------------------------------- 1 | #ifndef MD5_H 2 | #define MD5_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | typedef signed char int8_t; 9 | typedef short int16_t; 10 | typedef int int32_t; 11 | typedef long long int64_t; 12 | 13 | typedef unsigned char uint8_t; 14 | typedef unsigned short uint16_t; 15 | typedef unsigned int uint32_t; 16 | typedef unsigned long long uint64_t; 17 | 18 | typedef struct{ 19 | uint64_t size; // Size of input in bytes 20 | uint32_t buffer[4]; // Current accumulation of hash 21 | uint8_t input[64]; // Input to be used in the next step 22 | uint8_t digest[16]; // Result of algorithm 23 | }MD5Context; 24 | 25 | void md5Init(MD5Context *ctx); 26 | void md5Update(MD5Context *ctx, uint8_t *input, size_t input_len); 27 | void md5Finalize(MD5Context *ctx); 28 | void md5Step(uint32_t *buffer, uint32_t *input); 29 | 30 | void md5String(char *input, uint8_t *result); 31 | // void md5File(FILE *file, uint8_t *result); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /libcdi/Resource.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #include "resource.h" 4 | #include "version.h" 5 | 6 | #define APSTUDIO_READONLY_SYMBOLS 7 | ///////////////////////////////////////////////////////////////////////////// 8 | // 9 | // Generated from the TEXTINCLUDE 2 resource. 10 | // 11 | #include "winres.h" 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | #undef APSTUDIO_READONLY_SYMBOLS 15 | 16 | 17 | 18 | #ifdef APSTUDIO_INVOKED 19 | ///////////////////////////////////////////////////////////////////////////// 20 | // 21 | // TEXTINCLUDE 22 | // 23 | 24 | 1 TEXTINCLUDE 25 | BEGIN 26 | "resource.h\0" 27 | END 28 | 29 | 2 TEXTINCLUDE 30 | BEGIN 31 | "#include ""winres.h""\r\n" 32 | "\0" 33 | END 34 | 35 | 3 TEXTINCLUDE 36 | BEGIN 37 | "\r\n" 38 | "\0" 39 | END 40 | 41 | #endif // APSTUDIO_INVOKED 42 | 43 | 44 | ///////////////////////////////////////////////////////////////////////////// 45 | // 46 | // Icon 47 | // 48 | 49 | // Icon with lowest ID value placed first to ensure application icon 50 | // remains consistent on all systems. 51 | 52 | 53 | ///////////////////////////////////////////////////////////////////////////// 54 | 55 | ///////////////////////////////////////////////////////////////////////////// 56 | // 57 | // Version 58 | // 59 | 60 | VS_VERSION_INFO VERSIONINFO 61 | FILEVERSION LIBCDI_VERSION 62 | PRODUCTVERSION LIBCDI_VERSION 63 | FILEFLAGSMASK 0x3fL 64 | #ifdef _DEBUG 65 | FILEFLAGS 0x1L 66 | #else 67 | FILEFLAGS 0x0L 68 | #endif 69 | FILEOS 0x4L 70 | FILETYPE 0x1L 71 | FILESUBTYPE 0x0L 72 | BEGIN 73 | BLOCK "StringFileInfo" 74 | BEGIN 75 | BLOCK "040904b0" 76 | BEGIN 77 | VALUE "CompanyName", LIBCDI_COMPANY 78 | VALUE "FileVersion", LIBCDI_VERSION_STR 79 | VALUE "ProductVersion", LIBCDI_VERSION_STR 80 | VALUE "FileDescription", LIBCDI_FILEDESC 81 | VALUE "ProductName", LIBCDI_DLL 82 | VALUE "LegalCopyright", LIBCDI_COPYRIGHT 83 | END 84 | END 85 | BLOCK "VarFileInfo" 86 | BEGIN 87 | VALUE "Translation", 0x409, 1200 88 | END 89 | END 90 | 91 | #ifndef APSTUDIO_INVOKED 92 | ///////////////////////////////////////////////////////////////////////////// 93 | // 94 | // Generated from the TEXTINCLUDE 3 resource. 95 | // 96 | 97 | 98 | ///////////////////////////////////////////////////////////////////////////// 99 | #endif // not APSTUDIO_INVOKED 100 | 101 | -------------------------------------------------------------------------------- /libcdi/SPTIUtil.h: -------------------------------------------------------------------------------- 1 | //From DDK 2 | 3 | #define FILE_DEVICE_SCSI 0x0000001b 4 | #define IOCTL_SCSI_MINIPORT_IDENTIFY ((FILE_DEVICE_SCSI << 16) + 0x0501) 5 | #define IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS ((FILE_DEVICE_SCSI << 16) + 0x0502) 6 | #define IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS ((FILE_DEVICE_SCSI << 16) + 0x0503) 7 | #define IOCTL_SCSI_MINIPORT_ENABLE_SMART ((FILE_DEVICE_SCSI << 16) + 0x0504) 8 | #define IOCTL_SCSI_MINIPORT_DISABLE_SMART ((FILE_DEVICE_SCSI << 16) + 0x0505) 9 | 10 | #define IOCTL_SCSI_BASE FILE_DEVICE_CONTROLLER 11 | #define IOCTL_SCSI_PASS_THROUGH CTL_CODE(IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) 12 | 13 | // 14 | // Define values for pass-through DataIn field. 15 | // 16 | #define SCSI_IOCTL_DATA_OUT 0 17 | #define SCSI_IOCTL_DATA_IN 1 18 | #define SCSI_IOCTL_DATA_UNSPECIFIED 2 19 | 20 | // 21 | // Define the SCSI pass through structure. 22 | // 23 | typedef struct _SCSI_PASS_THROUGH { 24 | USHORT Length; 25 | UCHAR ScsiStatus; 26 | UCHAR PathId; 27 | UCHAR TargetId; 28 | UCHAR Lun; 29 | UCHAR CdbLength; 30 | UCHAR SenseInfoLength; 31 | UCHAR DataIn; 32 | ULONG DataTransferLength; 33 | ULONG TimeOutValue; 34 | ULONG_PTR DataBufferOffset; 35 | ULONG SenseInfoOffset; 36 | UCHAR Cdb[16]; 37 | }SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH; 38 | 39 | typedef struct _SCSI_PASS_THROUGH_WITH_BUFFERS { 40 | SCSI_PASS_THROUGH Spt; 41 | ULONG Filler; // realign buffers to double word boundary 42 | UCHAR SenseBuf[32]; 43 | UCHAR DataBuf[4096]; 44 | } SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS; 45 | 46 | typedef struct _SCSI_PASS_THROUGH_WITH_BUFFERS24 { 47 | SCSI_PASS_THROUGH Spt; 48 | UCHAR SenseBuf[24]; 49 | UCHAR DataBuf[4096]; 50 | } SCSI_PASS_THROUGH_WITH_BUFFERS24, *PSCSI_PASS_THROUGH_WITH_BUFFERS24; 51 | -------------------------------------------------------------------------------- /libcdi/SlotSpeedGetter.cpp: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*/ 2 | // Author : Minkyu Kim 3 | // Web : http://naraeon.net/ 4 | // https://github.com/ebangin127/ 5 | // License : MIT License 6 | /*---------------------------------------------------------------------------*/ 7 | 8 | #include "stdafx.h" 9 | #include "SlotSpeedGetter.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | //#pragma comment(lib, "Cfgmgr32.lib") 15 | #pragma comment(lib, "Setupapi.lib") 16 | #pragma comment(lib, "wbemuuid.lib") 17 | #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } 18 | 19 | DEFINE_GUID(GUID_DEVCLASS_SCSIADAPTER, 0x4D36E97B, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18); 20 | 21 | 22 | typedef BOOL(WINAPI *FN_SetupDiGetDeviceProperty)( 23 | __in HDEVINFO DeviceInfoSet, 24 | __in PSP_DEVINFO_DATA DeviceInfoData, 25 | __in const DEVPROPKEY *PropertyKey, 26 | __out DEVPROPTYPE *PropertyType, 27 | __out_opt PBYTE PropertyBuffer, 28 | __in DWORD PropertyBufferSize, 29 | __out_opt PDWORD RequiredSize, 30 | __in DWORD Flags 31 | ); 32 | 33 | CString GetStringValueFromQuery(IWbemServices* pIWbemServices, const CString query, const CString valuename) 34 | { 35 | IEnumWbemClassObject* pEnumCOMDevs = NULL; 36 | IWbemClassObject* pCOMDev = NULL; 37 | ULONG uReturned = 0; 38 | CString result = L""; 39 | 40 | try 41 | { 42 | if (SUCCEEDED(pIWbemServices->ExecQuery(_bstr_t(L"WQL"), 43 | _bstr_t(query), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumCOMDevs))) 44 | { 45 | while (pEnumCOMDevs && SUCCEEDED(pEnumCOMDevs->Next(10000, 1, &pCOMDev, &uReturned)) && uReturned == 1) 46 | { 47 | VARIANT pVal; 48 | VariantInit(&pVal); 49 | 50 | if (pCOMDev->Get(L"DeviceID", 0L, &pVal, NULL, NULL) == WBEM_S_NO_ERROR && pVal.vt > VT_NULL) 51 | { 52 | result = pVal.bstrVal; 53 | VariantClear(&pVal); 54 | } 55 | VariantInit(&pVal); 56 | } 57 | } 58 | } 59 | catch (...) 60 | { 61 | result = L""; 62 | } 63 | 64 | SAFE_RELEASE(pCOMDev); 65 | SAFE_RELEASE(pEnumCOMDevs); 66 | return result; 67 | } 68 | 69 | CString GetDeviceIDFromPhysicalDriveID(const INT physicalDriveId, const BOOL IsKernelVerEqualOrOver6) 70 | { 71 | const CString query2findstorage = L"ASSOCIATORS OF {Win32_DiskDrive.DeviceID='\\\\.\\PhysicalDrive%d'} WHERE ResultClass=Win32_PnPEntity"; 72 | const CString query2findcontroller = L"ASSOCIATORS OF {Win32_PnPEntity.DeviceID='%s'} WHERE AssocClass=Win32_SCSIControllerDevice"; 73 | CString query; 74 | CString result; 75 | IWbemLocator* pIWbemLocator = NULL; 76 | IWbemServices* pIWbemServices = NULL; 77 | //BOOL flag = FALSE; 78 | 79 | try 80 | { 81 | if (SUCCEEDED(CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, 82 | IID_IWbemLocator, (LPVOID *)&pIWbemLocator))) 83 | { 84 | long securityFlag = 0; 85 | if (IsKernelVerEqualOrOver6) { securityFlag = WBEM_FLAG_CONNECT_USE_MAX_WAIT; } 86 | if (SUCCEEDED(pIWbemLocator->ConnectServer(_bstr_t(L"\\\\.\\root\\cimv2"), 87 | NULL, NULL, 0L, securityFlag, NULL, NULL, &pIWbemServices))) 88 | { 89 | if (SUCCEEDED(CoSetProxyBlanket(pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, 90 | NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE))) 91 | { 92 | query.Format(query2findstorage, physicalDriveId); 93 | CString StorageID = GetStringValueFromQuery(pIWbemServices, query, L"DeviceID"); 94 | if(!StorageID.IsEmpty()) 95 | { 96 | query.Format(query2findcontroller.GetString(), StorageID.GetString()); 97 | CString ControllerID = GetStringValueFromQuery(pIWbemServices, query, L"DeviceID"); 98 | result = ControllerID; 99 | } 100 | else 101 | { 102 | result = L""; 103 | } 104 | } 105 | } 106 | } 107 | } 108 | catch (...) 109 | { 110 | result = L""; 111 | } 112 | SAFE_RELEASE(pIWbemServices); 113 | SAFE_RELEASE(pIWbemLocator); 114 | return result; 115 | } 116 | 117 | SlotMaxCurrSpeed ConvertOSResult(const OSSlotMaxCurrSpeed OSLevelResult) 118 | { 119 | SlotMaxCurrSpeed result{}; 120 | result.Current.LinkWidth = PCIeDataWidth(OSLevelResult.Current.LinkWidth); 121 | result.Current.SpecVersion = PCIeSpecification(OSLevelResult.Current.SpecVersion); 122 | result.Maximum.LinkWidth = PCIeDataWidth(OSLevelResult.Maximum.LinkWidth); 123 | result.Maximum.SpecVersion = PCIeSpecification(OSLevelResult.Maximum.SpecVersion); 124 | return result; 125 | } 126 | 127 | SlotMaxCurrSpeed GetSlotMaxCurrSpeedFromDeviceID(const CString DeviceID) 128 | { 129 | DWORD CurrentDevice = 0; 130 | OSSlotMaxCurrSpeed OSLevelResult{}; 131 | GUID SCSIAdapterGUID = GUID_DEVCLASS_SCSIADAPTER; 132 | HDEVINFO ClassDeviceInformations = SetupDiGetClassDevs(&SCSIAdapterGUID, nullptr, 0, DIGCF_PRESENT); 133 | 134 | BOOL LastResult{}; 135 | do 136 | { 137 | SP_DEVINFO_DATA DeviceInfoData = {sizeof(SP_DEVINFO_DATA)}; 138 | LastResult = SetupDiEnumDeviceInfo(ClassDeviceInformations, CurrentDevice, &DeviceInfoData); 139 | 140 | BOOL DeviceIDFound = FALSE; 141 | TCHAR DeviceIDBuffer[MAX_PATH] = {}; 142 | BOOL GetDeviceResult = CM_Get_Device_ID(DeviceInfoData.DevInst, DeviceIDBuffer, MAX_PATH, 0); 143 | DeviceIDFound = (GetDeviceResult == ERROR_SUCCESS) && (DeviceID.Compare(DeviceIDBuffer) == 0); 144 | if (LastResult && DeviceIDFound) 145 | { 146 | DEVPROPTYPE PropertyType{}; 147 | BYTE ResultBuffer[1024]{}; 148 | DWORD RequiredSize{}; 149 | 150 | const HMODULE hMod = LoadLibrary(TEXT("Setupapi.dll")); 151 | if (hMod && hMod != INVALID_HANDLE_VALUE) { 152 | FN_SetupDiGetDeviceProperty SetupDiGetDeviceProperty = 153 | (FN_SetupDiGetDeviceProperty)GetProcAddress(hMod, "SetupDiGetDevicePropertyW"); 154 | //Compatible with pre-vista era windows. 155 | if (SetupDiGetDeviceProperty) { 156 | SetupDiGetDeviceProperty(ClassDeviceInformations, &DeviceInfoData, 157 | &DEVPKEY_PciDevice_MaxLinkWidth, &PropertyType, ResultBuffer, 158 | sizeof(ResultBuffer), &RequiredSize, 0); 159 | OSLevelResult.Maximum.LinkWidth = ResultBuffer[0]; 160 | SetupDiGetDeviceProperty(ClassDeviceInformations, &DeviceInfoData, 161 | &DEVPKEY_PciDevice_MaxLinkSpeed, &PropertyType, ResultBuffer, 162 | sizeof(ResultBuffer), &RequiredSize, 0); 163 | OSLevelResult.Maximum.SpecVersion = ResultBuffer[0]; 164 | 165 | SetupDiGetDeviceProperty(ClassDeviceInformations, &DeviceInfoData, 166 | &DEVPKEY_PciDevice_CurrentLinkWidth, &PropertyType, ResultBuffer, 167 | sizeof(ResultBuffer), &RequiredSize, 0); 168 | OSLevelResult.Current.LinkWidth = ResultBuffer[0]; 169 | SetupDiGetDeviceProperty(ClassDeviceInformations, &DeviceInfoData, 170 | &DEVPKEY_PciDevice_CurrentLinkSpeed, &PropertyType, ResultBuffer, 171 | sizeof(ResultBuffer), &RequiredSize, 0); 172 | OSLevelResult.Current.SpecVersion = ResultBuffer[0]; 173 | } 174 | } 175 | break; 176 | } 177 | 178 | ++CurrentDevice; 179 | } while (LastResult); 180 | 181 | return ConvertOSResult(OSLevelResult); 182 | } 183 | 184 | SlotMaxCurrSpeed GetPCIeSlotSpeed(const INT physicalDriveId, const BOOL IsKernelVerEqualOrOver6) 185 | { 186 | CString DeviceID = GetDeviceIDFromPhysicalDriveID(physicalDriveId, IsKernelVerEqualOrOver6); 187 | return GetSlotMaxCurrSpeedFromDeviceID(DeviceID); 188 | } 189 | 190 | CString SlotSpeedToString(SlotSpeed speedtoconv) 191 | { 192 | CString result = L""; 193 | if (speedtoconv.SpecVersion == 0 || speedtoconv.LinkWidth == 0) 194 | { 195 | result.Format(L"----"); 196 | } 197 | else 198 | { 199 | result.Format(L"PCIe %d.0 x%d", speedtoconv.SpecVersion, speedtoconv.LinkWidth); 200 | } 201 | return result; 202 | } -------------------------------------------------------------------------------- /libcdi/SlotSpeedGetter.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*/ 2 | // Author : Minkyu Kim 3 | // Web : http://naraeon.net/ 4 | // https://github.com/ebangin127/ 5 | // License : MIT License 6 | /*---------------------------------------------------------------------------*/ 7 | 8 | #pragma once 9 | #include 10 | #include 11 | 12 | typedef enum _PCIeSpecification { 13 | PCIe1d0 = 1, 14 | PCIe2d0 = 2, 15 | PCIe3d0 = 3, 16 | PCIe4d0 = 4, 17 | PCIe5d0 = 5 18 | } PCIeSpecification; 19 | 20 | typedef enum _PCIeDataWidth { 21 | PCIex1 = 1, 22 | PCIex2 = 2, 23 | PCIex4 = 4, 24 | PCIex8 = 8, 25 | PCIex12 = 12, 26 | PCIex16 = 16, 27 | PCIex32 = 32 28 | } PCIeDataWidth; 29 | 30 | typedef struct _SlotSpeed { 31 | PCIeSpecification SpecVersion; 32 | PCIeDataWidth LinkWidth; 33 | } SlotSpeed; 34 | 35 | typedef struct _SlotMaxCurrSpeed { 36 | SlotSpeed Maximum; 37 | SlotSpeed Current; 38 | } SlotMaxCurrSpeed; 39 | 40 | typedef struct _OSSlotSpeed { 41 | BYTE SpecVersion; 42 | BYTE LinkWidth; 43 | } OSSlotSpeed; 44 | 45 | typedef struct _OSSlotMaxCurrSpeed { 46 | OSSlotSpeed Maximum; 47 | OSSlotSpeed Current; 48 | } OSSlotMaxCurrSpeed; 49 | 50 | #define DEFINE_PCI_DEVICE_DEVPKEY(_DevPkeyName, _Pid) \ 51 | DEFINE_DEVPROPKEY((_DevPkeyName), 0x3ab22e31, 0x8264, 0x4b4e, 0x9a, 0xf5, 0xa8, 0xd2, 0xd8, 0xe3, 0x3e, 0x62, (_Pid)) 52 | 53 | DEFINE_PCI_DEVICE_DEVPKEY(DEVPKEY_PciDevice_CurrentLinkSpeed, 9); 54 | DEFINE_PCI_DEVICE_DEVPKEY(DEVPKEY_PciDevice_CurrentLinkWidth, 10); 55 | DEFINE_PCI_DEVICE_DEVPKEY(DEVPKEY_PciDevice_MaxLinkSpeed, 11); 56 | DEFINE_PCI_DEVICE_DEVPKEY(DEVPKEY_PciDevice_MaxLinkWidth, 12); 57 | 58 | SlotMaxCurrSpeed GetPCIeSlotSpeed(const INT physicalDriveId, const BOOL IsKernelVerEqualOrOver6); 59 | CString SlotSpeedToString(SlotSpeed speedtoconv); -------------------------------------------------------------------------------- /libcdi/Source.def: -------------------------------------------------------------------------------- 1 | LIBRARY LIBCDI 2 | EXPORTS 3 | cdi_get_version 4 | 5 | cdi_create_smart 6 | cdi_destroy_smart 7 | cdi_init_smart 8 | cdi_update_smart 9 | cdi_get_disk_count 10 | 11 | cdi_get_bool 12 | cdi_get_int 13 | cdi_get_dword 14 | cdi_get_string 15 | cdi_free_string 16 | 17 | cdi_get_smart_format 18 | cdi_get_smart_id 19 | cdi_get_smart_value 20 | cdi_get_smart_status 21 | cdi_get_smart_name 22 | -------------------------------------------------------------------------------- /libcdi/StorageQuery.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace StorageQuery { 4 | typedef enum { 5 | StorageDeviceProperty = 0, 6 | StorageAdapterProperty, 7 | StorageDeviceIdProperty, 8 | StorageDeviceUniqueIdProperty, 9 | StorageDeviceWriteCacheProperty, 10 | StorageMiniportProperty, 11 | StorageAccessAlignmentProperty, 12 | StorageDeviceSeekPenaltyProperty, 13 | StorageDeviceTrimProperty, 14 | StorageDeviceWriteAggregationProperty, 15 | StorageDeviceDeviceTelemetryProperty, 16 | StorageDeviceLBProvisioningProperty, 17 | StorageDevicePowerProperty, 18 | StorageDeviceCopyOffloadProperty, 19 | StorageDeviceResiliencyProperty, 20 | StorageDeviceMediumProductType, 21 | StorageDeviceRpmbProperty, 22 | StorageDeviceIoCapabilityProperty = 48, 23 | StorageAdapterProtocolSpecificProperty, 24 | StorageDeviceProtocolSpecificProperty, 25 | StorageAdapterTemperatureProperty, 26 | StorageDeviceTemperatureProperty, 27 | StorageAdapterPhysicalTopologyProperty, 28 | StorageDevicePhysicalTopologyProperty, 29 | StorageDeviceAttributesProperty, 30 | } TStoragePropertyId; 31 | 32 | typedef enum { 33 | PropertyStandardQuery = 0, 34 | PropertyExistsQuery, 35 | PropertyMaskQuery, 36 | PropertyQueryMaxDefined 37 | } TStorageQueryType; 38 | 39 | typedef struct { 40 | TStoragePropertyId PropertyId; 41 | TStorageQueryType QueryType; 42 | } TStoragePropertyQuery; 43 | 44 | typedef enum { 45 | ProtocolTypeUnknown = 0x00, 46 | ProtocolTypeScsi, 47 | ProtocolTypeAta, 48 | ProtocolTypeNvme, 49 | ProtocolTypeSd, 50 | ProtocolTypeProprietary = 0x7E, 51 | ProtocolTypeMaxReserved = 0x7F 52 | } TStroageProtocolType; 53 | 54 | typedef struct { 55 | TStroageProtocolType ProtocolType; 56 | DWORD DataType; 57 | DWORD ProtocolDataRequestValue; 58 | DWORD ProtocolDataRequestSubValue; 59 | DWORD ProtocolDataOffset; 60 | DWORD ProtocolDataLength; 61 | DWORD FixedProtocolReturnData; 62 | DWORD Reserved[3]; 63 | } TStorageProtocolSpecificData; 64 | 65 | typedef enum { 66 | NVMeDataTypeUnknown = 0, 67 | NVMeDataTypeIdentify, 68 | NVMeDataTypeLogPage, 69 | NVMeDataTypeFeature, 70 | } TStorageProtocolNVMeDataType; 71 | 72 | typedef struct { 73 | TStoragePropertyQuery Query; 74 | TStorageProtocolSpecificData ProtocolSpecific; 75 | BYTE Buffer[4096]; 76 | } TStorageQueryWithBuffer; 77 | } 78 | -------------------------------------------------------------------------------- /libcdi/libcdi.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "AtaSmart.h" 3 | #include "NVMeInterpreter.h" 4 | #include "smartids.h" 5 | 6 | #define LIBCDI_IMPLEMENTATION 7 | #include "libcdi.h" 8 | 9 | #include "UtilityFx.h" 10 | 11 | #include "version.h" 12 | 13 | extern "C" CONST CHAR* WINAPI 14 | cdi_get_version() 15 | { 16 | return QUOTE(LIBCDI_MAJOR_VERSION.LIBCDI_MINOR_VERSION.LIBCDI_MICRO_VERSION); 17 | } 18 | 19 | #define DEBUG_MODE_NONE 0U 20 | #define DEBUG_MODE_LOG 1U 21 | #define DEBUG_MODE_MESSAGE 2U 22 | 23 | #define DEBUG_MODE DEBUG_MODE_NONE 24 | 25 | extern "C" CDI_SMART* WINAPI 26 | cdi_create_smart() 27 | { 28 | SetDebugMode(DEBUG_MODE); 29 | //(void)CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); 30 | return new CDI_SMART; 31 | } 32 | 33 | extern "C" VOID WINAPI 34 | cdi_destroy_smart(CDI_SMART * ptr) 35 | { 36 | delete ptr; 37 | //CoUninitialize(); 38 | } 39 | 40 | inline BOOL 41 | check_flag(UINT64 flags, UINT64 mask) 42 | { 43 | return (flags & mask) ? TRUE : FALSE; 44 | } 45 | 46 | extern "C" VOID WINAPI 47 | cdi_init_smart(CDI_SMART * ptr, UINT64 flags) 48 | { 49 | BOOL change_disk = TRUE; 50 | 51 | ptr->FlagNoWakeUp = check_flag(flags, CDI_FLAG_NO_WAKEUP); 52 | ptr->SetAtaPassThroughSmart(check_flag(flags, CDI_FLAG_ATA_PASS_THROUGH)); 53 | 54 | ptr->FlagNvidiaController = check_flag(flags, CDI_FLAG_ENABLE_NVIDIA); 55 | ptr->FlagMarvellController = check_flag(flags, CDI_FLAG_ENABLE_MARVELL); 56 | ptr->FlagUsbSat = check_flag(flags, CDI_FLAG_ENABLE_USB_SAT); 57 | ptr->FlagUsbSunplus = check_flag(flags, CDI_FLAG_ENABLE_USB_SUNPLUS); 58 | ptr->FlagUsbIodata = check_flag(flags, CDI_FLAG_ENABLE_USB_IODATA); 59 | ptr->FlagUsbLogitec = check_flag(flags, CDI_FLAG_ENABLE_USB_LOGITEC); 60 | ptr->FlagUsbProlific = check_flag(flags, CDI_FLAG_ENABLE_USB_PROLIFIC); 61 | ptr->FlagUsbJmicron = check_flag(flags, CDI_FLAG_ENABLE_USB_JMICRON); 62 | ptr->FlagUsbCypress = check_flag(flags, CDI_FLAG_ENABLE_USB_CYPRESS); 63 | ptr->FlagUsbMemory = check_flag(flags, CDI_FLAG_ENABLE_USB_MEMORY); 64 | ptr->FlagUsbNVMeJMicron = check_flag(flags, CDI_FLAG_ENABLE_NVME_JMICRON); 65 | ptr->FlagUsbNVMeASMedia = check_flag(flags, CDI_FLAG_ENABLE_NVME_ASMEDIA); 66 | ptr->FlagUsbNVMeRealtek = check_flag(flags, CDI_FLAG_ENABLE_NVME_REALTEK); 67 | ptr->FlagMegaRAID = check_flag(flags, CDI_FLAG_ENABLE_MEGA_RAID); 68 | ptr->FlagIntelVROC = check_flag(flags, CDI_FLAG_ENABLE_INTEL_VROC); 69 | ptr->FlagUsbASM1352R = check_flag(flags, CDI_FLAG_ENABLE_ASM1352R); 70 | ptr->FlagAMD_RC2 = check_flag(flags, CDI_FLAG_ENABLE_AMD_RC2); 71 | ptr->FlagUsbRealtek9220DP = check_flag(flags, CDI_FLAG_ENABLE_REALTEK_9220DP); 72 | 73 | ptr->Init(check_flag(flags, CDI_FLAG_USE_WMI), 74 | check_flag(flags, CDI_FLAG_ADVANCED_SEARCH), 75 | &change_disk, 76 | check_flag(flags, CDI_FLAG_WORKAROUND_HD204UI), 77 | check_flag(flags, CDI_FLAG_WORKAROUND_ADATA), 78 | check_flag(flags, CDI_FLAG_HIDE_NO_SMART), 79 | check_flag(flags, CDI_FLAG_SORT_DRIVE_LETTER), 80 | check_flag(flags, CDI_FLAG_HIDE_RAID_VOLUME)); 81 | for (INT i = 0; i < ptr->vars.GetCount(); i++) 82 | { 83 | if (ptr->vars[i].IsSsd) 84 | ptr->vars[i].AlarmTemperature = 60; 85 | else 86 | ptr->vars[i].AlarmTemperature = 50; 87 | ptr->vars[i].AlarmHealthStatus = 1; 88 | 89 | ptr->vars[i].Threshold05 = 1; 90 | ptr->vars[i].ThresholdC5 = 1; 91 | ptr->vars[i].ThresholdC6 = 1; 92 | ptr->vars[i].ThresholdFF = 10; 93 | 94 | ptr->vars[i].DiskStatus = ptr->CheckDiskStatus(i); 95 | } 96 | } 97 | 98 | extern "C" DWORD WINAPI 99 | cdi_update_smart(CDI_SMART * ptr, INT index) 100 | { 101 | return ptr->UpdateSmartInfo(index); 102 | } 103 | 104 | inline WCHAR* cs_to_wcs(const CString& str) 105 | { 106 | size_t len = str.GetLength() + 1; 107 | auto ptr = (WCHAR*)CoTaskMemAlloc(len * sizeof(WCHAR)); 108 | wcscpy_s(ptr, len, str.GetString()); 109 | return ptr; 110 | } 111 | 112 | extern "C" INT WINAPI 113 | cdi_get_disk_count(CDI_SMART * ptr) 114 | { 115 | return (INT)ptr->vars.GetCount(); 116 | } 117 | 118 | extern "C" BOOL WINAPI 119 | cdi_get_bool(CDI_SMART * ptr, INT index, enum CDI_ATA_BOOL attr) 120 | { 121 | switch (attr) 122 | { 123 | case CDI_BOOL_SSD: 124 | return ptr->vars[index].IsSsd; 125 | case CDI_BOOL_SSD_NVME: 126 | return (ptr->vars[index].DiskVendorId == CAtaSmart::SSD_VENDOR_NVME) ? TRUE : FALSE; 127 | case CDI_BOOL_SMART: 128 | return ptr->vars[index].IsSmartSupported; 129 | case CDI_BOOL_LBA48: 130 | return ptr->vars[index].IsLba48Supported; 131 | case CDI_BOOL_AAM: 132 | return ptr->vars[index].IsAamSupported; 133 | case CDI_BOOL_APM: 134 | return ptr->vars[index].IsApmSupported; 135 | case CDI_BOOL_NCQ: 136 | return ptr->vars[index].IsNcqSupported; 137 | case CDI_BOOL_NV_CACHE: 138 | return ptr->vars[index].IsNvCacheSupported; 139 | case CDI_BOOL_DEVSLP: 140 | return ptr->vars[index].IsDeviceSleepSupported; 141 | case CDI_BOOL_STREAMING: 142 | return ptr->vars[index].IsStreamingSupported; 143 | case CDI_BOOL_GPL: 144 | return ptr->vars[index].IsGplSupported; 145 | case CDI_BOOL_TRIM: 146 | return ptr->vars[index].IsTrimSupported; 147 | case CDI_BOOL_VOLATILE_WRITE_CACHE: 148 | return ptr->vars[index].IsVolatileWriteCachePresent; 149 | case CDI_BOOL_SMART_ENABLED: 150 | return ptr->vars[index].IsSmartEnabled; 151 | case CDI_BOOL_AAM_ENABLED: 152 | return ptr->vars[index].IsAamEnabled; 153 | case CDI_BOOL_APM_ENABLED: 154 | return ptr->vars[index].IsApmEnabled; 155 | } 156 | return FALSE; 157 | } 158 | 159 | extern "C" INT WINAPI 160 | cdi_get_int(CDI_SMART * ptr, INT index, enum CDI_ATA_INT attr) 161 | { 162 | switch (attr) 163 | { 164 | case CDI_INT_DISK_ID: 165 | return ptr->vars[index].PhysicalDriveId; 166 | case CDI_INT_DISK_STATUS: 167 | return (INT)ptr->vars[index].DiskStatus; 168 | case CDI_INT_SCSI_PORT: 169 | return ptr->vars[index].ScsiPort; 170 | case CDI_INT_SCSI_TARGET_ID: 171 | return ptr->vars[index].ScsiTargetId; 172 | case CDI_INT_SCSI_BUS: 173 | return ptr->vars[index].ScsiBus; 174 | case CDI_INT_POWER_ON_HOURS: 175 | { 176 | INT div = 1; 177 | INT num = ptr->vars[index].MeasuredPowerOnHours; 178 | if (num > 0) 179 | { 180 | if (ptr->vars[index].MeasuredTimeUnitType == CAtaSmart::POWER_ON_MINUTES && ptr->vars[index].IsMaxtorMinute) 181 | div = 60; 182 | } 183 | else 184 | { 185 | num = ptr->vars[index].DetectedPowerOnHours; 186 | if (num > 0 && ptr->vars[index].DetectedTimeUnitType == CAtaSmart::POWER_ON_MINUTES && ptr->vars[index].IsMaxtorMinute) 187 | div = 60; 188 | } 189 | return num / div; 190 | } 191 | case CDI_INT_TEMPERATURE: 192 | return ptr->vars[index].Temperature; 193 | case CDI_INT_TEMPERATURE_ALARM: 194 | return ptr->vars[index].AlarmTemperature; 195 | case CDI_INT_HOST_WRITES: 196 | return ptr->vars[index].HostWrites; 197 | case CDI_INT_HOST_READS: 198 | return ptr->vars[index].HostReads; 199 | case CDI_INT_NAND_WRITES: 200 | return ptr->vars[index].NandWrites; 201 | case CDI_INT_GB_ERASED: 202 | return ptr->vars[index].GBytesErased; 203 | case CDI_INT_WEAR_LEVELING_COUNT: 204 | return ptr->vars[index].WearLevelingCount; 205 | case CDI_INT_LIFE: 206 | return ptr->vars[index].Life; 207 | case CDI_INT_MAX_ATTRIBUTE: 208 | return CAtaSmart::MAX_ATTRIBUTE; 209 | } 210 | return -1; 211 | } 212 | 213 | extern "C" DWORD WINAPI 214 | cdi_get_dword(CDI_SMART * ptr, INT index, enum CDI_ATA_DWORD attr) 215 | { 216 | switch (attr) 217 | { 218 | case CDI_DWORD_DISK_SIZE: 219 | return ptr->vars[index].TotalDiskSize; 220 | case CDI_DWORD_LOGICAL_SECTOR_SIZE: 221 | return ptr->vars[index].LogicalSectorSize; 222 | case CDI_DWORD_PHYSICAL_SECTOR_SIZE: 223 | return ptr->vars[index].PhysicalSectorSize; 224 | case CDI_DWORD_BUFFER_SIZE: 225 | return ptr->vars[index].BufferSize; 226 | case CDI_DWORD_ATTR_COUNT: 227 | return ptr->vars[index].AttributeCount; 228 | case CDI_DWORD_POWER_ON_COUNT: 229 | return ptr->vars[index].PowerOnCount; 230 | case CDI_DWORD_ROTATION_RATE: 231 | return ptr->vars[index].NominalMediaRotationRate; 232 | case CDI_DWORD_DRIVE_LETTER: 233 | return ptr->vars[index].DriveLetterMap; 234 | case CDI_DWORD_DISK_VENDOR_ID: 235 | return ptr->vars[index].DiskVendorId; 236 | } 237 | return 0; 238 | } 239 | 240 | extern "C" WCHAR* WINAPI 241 | cdi_get_string(CDI_SMART * ptr, INT index, enum CDI_ATA_STRING attr) 242 | { 243 | switch (attr) 244 | { 245 | case CDI_STRING_SN: 246 | return cs_to_wcs(ptr->vars[index].SerialNumber); 247 | case CDI_STRING_FIRMWARE: 248 | return cs_to_wcs(ptr->vars[index].FirmwareRev); 249 | case CDI_STRING_MODEL: 250 | return cs_to_wcs(ptr->vars[index].Model); 251 | case CDI_STRING_DRIVE_MAP: 252 | return cs_to_wcs(ptr->vars[index].DriveMap); 253 | case CDI_STRING_TRANSFER_MODE_MAX: 254 | return cs_to_wcs(ptr->vars[index].MaxTransferMode); 255 | case CDI_STRING_TRANSFER_MODE_CUR: 256 | return cs_to_wcs(ptr->vars[index].CurrentTransferMode); 257 | case CDI_STRING_INTERFACE: 258 | return cs_to_wcs(ptr->vars[index].Interface); 259 | case CDI_STRING_VERSION_MAJOR: 260 | return cs_to_wcs(ptr->vars[index].MajorVersion); 261 | case CDI_STRING_VERSION_MINOR: 262 | return cs_to_wcs(ptr->vars[index].MinorVersion); 263 | case CDI_STRING_PNP_ID: 264 | return cs_to_wcs(ptr->vars[index].PnpDeviceId); 265 | case CDI_STRING_SMART_KEY: 266 | return cs_to_wcs(ptr->vars[index].SmartKeyName); 267 | } 268 | return nullptr; 269 | } 270 | 271 | extern "C" VOID WINAPI 272 | cdi_free_string(WCHAR* ptr) 273 | { 274 | if (ptr) 275 | CoTaskMemFree(ptr); 276 | } 277 | 278 | extern "C" WCHAR* WINAPI 279 | cdi_get_smart_format(CDI_SMART * ptr, INT index) 280 | { 281 | CString fmt; 282 | if (ptr->vars[index].DiskVendorId == CAtaSmart::SSD_VENDOR_SANDFORCE) 283 | { 284 | if (ptr->vars[index].IsThresholdCorrect) 285 | fmt = _T("Cur Wor Thr RawValues(7)"); 286 | else 287 | fmt = _T("Cur Wor --- RawValues(7)"); 288 | } 289 | else if (ptr->vars[index].DiskVendorId == CAtaSmart::SSD_VENDOR_JMICRON 290 | && ptr->vars[index].IsRawValues8) 291 | fmt = _T("Cur RawValues(8)"); 292 | else if (ptr->vars[index].DiskVendorId == CAtaSmart::SSD_VENDOR_INDILINX) 293 | fmt = _T("RawValues(8)"); 294 | else if (ptr->vars[index].DiskVendorId == CAtaSmart::SSD_VENDOR_NVME) 295 | fmt = _T("RawValues(7)"); 296 | else 297 | { 298 | if (ptr->vars[index].IsThresholdCorrect) 299 | fmt = _T("Cur Wor Thr RawValues(6)"); 300 | else 301 | fmt = _T("Cur Wor --- RawValues(6)"); 302 | } 303 | 304 | return cs_to_wcs(fmt); 305 | } 306 | 307 | extern "C" BYTE WINAPI 308 | cdi_get_smart_id(CDI_SMART * ptr, INT index, INT attr) 309 | { 310 | return ptr->vars[index].Attribute[attr].Id; 311 | } 312 | 313 | extern "C" WCHAR* WINAPI 314 | cdi_get_smart_value(CDI_SMART * ptr, INT index, INT attr, BOOL hex) 315 | { 316 | CString cstr; 317 | UINT64 raw; 318 | SMART_ATTRIBUTE* data = &ptr->vars[index].Attribute[attr]; 319 | 320 | if (ptr->vars[index].DiskVendorId == CAtaSmart::SSD_VENDOR_SANDFORCE) 321 | { 322 | raw = ((UINT64)data->Reserved << 48) + 323 | ((UINT64)data->RawValue[5] << 40) + 324 | ((UINT64)data->RawValue[4] << 32) + 325 | ((UINT64)data->RawValue[3] << 24) + 326 | ((UINT64)data->RawValue[2] << 16) + 327 | ((UINT64)data->RawValue[1] << 8) + 328 | ((UINT64)data->RawValue[0]); 329 | if (ptr->vars[index].IsThresholdCorrect) 330 | cstr.Format(hex ? _T("%3d %3d %3d %014llX") : _T("%3d %3d %3d %I64u"), 331 | data->CurrentValue, data->WorstValue, ptr->vars[index].Threshold[attr].ThresholdValue, raw); 332 | else 333 | cstr.Format(hex ? _T("%3d %3d --- %014llX") : _T("%3d %3d --- %I64u"), 334 | data->CurrentValue, data->WorstValue, raw); 335 | } 336 | else if (ptr->vars[index].DiskVendorId == CAtaSmart::SSD_VENDOR_JMICRON 337 | && ptr->vars[index].IsRawValues8) 338 | { 339 | raw = ((UINT64)data->Reserved << 56) + 340 | ((UINT64)data->RawValue[5] << 48) + 341 | ((UINT64)data->RawValue[4] << 40) + 342 | ((UINT64)data->RawValue[3] << 32) + 343 | ((UINT64)data->RawValue[2] << 24) + 344 | ((UINT64)data->RawValue[1] << 16) + 345 | ((UINT64)data->RawValue[0] << 8) + 346 | ((UINT64)data->WorstValue); 347 | cstr.Format(hex ? _T("%3d %016llX") : _T("%3d %I64u"), 348 | data->CurrentValue, raw); 349 | } 350 | else if (ptr->vars[index].DiskVendorId == CAtaSmart::SSD_VENDOR_INDILINX) 351 | { 352 | raw = ((UINT64)data->RawValue[5] << 56) + 353 | ((UINT64)data->RawValue[4] << 48) + 354 | ((UINT64)data->RawValue[3] << 40) + 355 | ((UINT64)data->RawValue[2] << 32) + 356 | ((UINT64)data->RawValue[1] << 24) + 357 | ((UINT64)data->RawValue[0] << 16) + 358 | ((UINT64)data->WorstValue << 8) + 359 | ((UINT64)data->CurrentValue); 360 | cstr.Format(hex ? _T("%016llX") : _T("%I64u"), raw); 361 | } 362 | else if (ptr->vars[index].DiskVendorId == CAtaSmart::SSD_VENDOR_NVME) 363 | { 364 | raw = ((UINT64)data->Reserved << 48) + 365 | ((UINT64)data->RawValue[5] << 40) + 366 | ((UINT64)data->RawValue[4] << 32) + 367 | ((UINT64)data->RawValue[3] << 24) + 368 | ((UINT64)data->RawValue[2] << 16) + 369 | ((UINT64)data->RawValue[1] << 8) + 370 | ((UINT64)data->RawValue[0]); 371 | cstr.Format(hex ? _T("%014llX") : _T("%I64u"), raw); 372 | } 373 | else 374 | { 375 | raw = ((UINT64)data->RawValue[5] << 40) + 376 | ((UINT64)data->RawValue[4] << 32) + 377 | ((UINT64)data->RawValue[3] << 24) + 378 | ((UINT64)data->RawValue[2] << 16) + 379 | ((UINT64)data->RawValue[1] << 8) + 380 | ((UINT64)data->RawValue[0]); 381 | if (ptr->vars[index].IsThresholdCorrect) 382 | { 383 | cstr.Format(hex ? _T("%3d %3d %3d %012llX") : _T("%3d %3d %3d %I64u"), 384 | data->CurrentValue, data->WorstValue, ptr->vars[index].Threshold[attr].ThresholdValue, raw); 385 | } 386 | else 387 | { 388 | cstr.Format(hex ? _T("%3d %3d --- %012llX") : _T("%3d %3d --- %I64u"), 389 | data->CurrentValue, data->WorstValue, raw); 390 | } 391 | } 392 | 393 | return cs_to_wcs(cstr); 394 | } 395 | 396 | // DiskInfoDlgUpdate.cpp 397 | // BOOL CDiskInfoDlg::UpdateListCtrl(DWORD i) 398 | extern "C" INT WINAPI 399 | cdi_get_smart_status(CDI_SMART * ptr, INT index, INT attr) 400 | { 401 | INT stat = CDI_DISK_STATUS_UNKNOWN; 402 | const BYTE attr_id = ptr->vars[index].Attribute[attr].Id; 403 | const DWORD ven_id = ptr->vars[index].DiskVendorId; 404 | 405 | if (attr_id == 0x00 || attr_id == 0xFF) 406 | return stat; 407 | 408 | if (ptr->vars[index].IsNVMe) 409 | { 410 | stat = CDI_DISK_STATUS_GOOD; 411 | if (ptr->vars[index].Model.Find(_T("Parallels")) == 0 412 | || ptr->vars[index].Model.Find(_T("VMware")) == 0 413 | || ptr->vars[index].Model.Find(_T("QEMU")) == 0) stat = CDI_DISK_STATUS_UNKNOWN; 414 | else 415 | { 416 | switch (attr_id) 417 | { 418 | case 0x01: 419 | if (ptr->vars[index].Attribute[attr].RawValue[0]) stat = CDI_DISK_STATUS_BAD; 420 | break; 421 | case 0x02: 422 | { 423 | const int temperature = (int)(MAKEWORD(ptr->vars[index].Attribute[1].RawValue[0], ptr->vars[index].Attribute[1].RawValue[1])) - 273; 424 | if (temperature >= ptr->vars[index].AlarmTemperature) stat = CDI_DISK_STATUS_BAD; 425 | else if (temperature == ptr->vars[index].AlarmTemperature) stat = CDI_DISK_STATUS_CAUTION; 426 | } 427 | break; 428 | case 0x03: 429 | // 2022/10/02 Workaround for no support Available Spare Threshold devices 430 | // https://github.com/hiyohiyo/CrystalDiskInfo/issues/186 431 | if (ptr->vars[index].Attribute[3].RawValue[0] > 100) 432 | stat = CDI_DISK_STATUS_GOOD; 433 | // 2022/03/26 Workaround for WD_BLACK AN1500 (No support Available Spare/Available Spare Threshold) 434 | else if (ptr->vars[index].Attribute[2].RawValue[0] == 0 && ptr->vars[index].Attribute[3].RawValue[0] == 0) 435 | stat = CDI_DISK_STATUS_GOOD; 436 | else if (ptr->vars[index].Attribute[2].RawValue[0] < ptr->vars[index].Attribute[3].RawValue[0]) 437 | stat = CDI_DISK_STATUS_BAD; 438 | else if (ptr->vars[index].Attribute[2].RawValue[0] == ptr->vars[index].Attribute[3].RawValue[0] && ptr->vars[index].Attribute[3].RawValue[0] != 100) 439 | stat = CDI_DISK_STATUS_CAUTION; 440 | break; 441 | case 0x05: 442 | if ((100 - ptr->vars[index].Attribute[attr].RawValue[0]) <= ptr->vars[index].ThresholdFF) 443 | stat = CDI_DISK_STATUS_CAUTION; 444 | break; 445 | } 446 | } 447 | } 448 | else if (ptr->vars[index].IsSmartCorrect && ptr->vars[index].IsThresholdCorrect && !ptr->vars[index].IsThresholdBug) 449 | { 450 | if (!ptr->vars[index].IsSsd && 451 | (attr_id == 0x05 // Reallocated Sectors Count 452 | || attr_id == 0xC5 // Current Pending Sector Count 453 | || attr_id == 0xC6 // Off-Line Scan Uncorrectable Sector Count 454 | )) 455 | { 456 | if (ptr->vars[index].Threshold[attr].ThresholdValue 457 | && ptr->vars[index].Attribute[attr].CurrentValue < ptr->vars[index].Threshold[attr].ThresholdValue) 458 | stat = CDI_DISK_STATUS_BAD; 459 | else 460 | { 461 | WORD threshold = 0; 462 | switch (attr_id) 463 | { 464 | case 0x05: 465 | threshold = ptr->vars[index].Threshold05; 466 | break; 467 | case 0xC5: 468 | threshold = ptr->vars[index].ThresholdC5; 469 | break; 470 | case 0xC6: 471 | threshold = ptr->vars[index].ThresholdC6; 472 | break; 473 | } 474 | if (threshold && (MAKEWORD(ptr->vars[index].Attribute[attr].RawValue[0], ptr->vars[index].Attribute[attr].RawValue[1])) >= threshold) 475 | stat = CDI_DISK_STATUS_CAUTION; 476 | else 477 | stat = CDI_DISK_STATUS_GOOD; 478 | } 479 | } 480 | // [2021/12/15] Workaround for SanDisk USB Memory 481 | else if (attr_id == 0xE8 && ptr->vars[index].FlagLifeSanDiskUsbMemory) 482 | stat = CDI_DISK_STATUS_GOOD; 483 | // Temperature 484 | else if (attr_id == 0xC2) 485 | stat = CDI_DISK_STATUS_GOOD; 486 | // End-to-End Error 487 | // https://crystalmark.info/bbs/c-board.cgi?cmd=one;no=1090;id=diskinfo#1090 488 | // http://h20000.www2.hp.com/bc/docs/support/SupportManual/c01159621/c01159621.pdf 489 | else if (attr_id == 0xB8) 490 | stat = CDI_DISK_STATUS_GOOD; 491 | // Life for WDC/SanDisk 492 | else if (attr_id == 0xE6 && (ptr->vars[index].DiskVendorId == ptr->SSD_VENDOR_WDC || ptr->vars[index].DiskVendorId == ptr->SSD_VENDOR_SANDISK)) 493 | { 494 | int life = -1; 495 | 496 | if (ptr->vars[index].FlagLifeSanDiskUsbMemory) 497 | life = -1; 498 | else if (ptr->vars[index].FlagLifeSanDisk0_1) 499 | life = 100 - (ptr->vars[index].Attribute[attr].RawValue[1] * 256 + ptr->vars[index].Attribute[attr].RawValue[0]) / 100; 500 | else if (ptr->vars[index].FlagLifeSanDisk1) 501 | life = 100 - ptr->vars[index].Attribute[attr].RawValue[1]; 502 | else if (ptr->vars[index].FlagLifeSanDiskLenovo) 503 | life = ptr->vars[index].Attribute[attr].CurrentValue; 504 | else 505 | life = 100 - ptr->vars[index].Attribute[attr].RawValue[1]; 506 | 507 | if (life < 0) 508 | life = 0; 509 | 510 | if (ptr->vars[index].FlagLifeSanDiskUsbMemory) 511 | stat = CDI_DISK_STATUS_GOOD; 512 | else if (life == 0) 513 | stat = CDI_DISK_STATUS_BAD; 514 | else if (life <= ptr->vars[index].ThresholdFF) 515 | stat = CDI_DISK_STATUS_CAUTION; 516 | else 517 | stat = CDI_DISK_STATUS_GOOD; 518 | } 519 | // Life 520 | else if ( 521 | (attr_id == 0xA9 && (ven_id == ptr->SSD_VENDOR_REALTEK || (ven_id == ptr->SSD_VENDOR_KINGSTON && ptr->vars[index].HostReadsWritesUnit == ptr->HOST_READS_WRITES_32MB) || ven_id == ptr->SSD_VENDOR_SILICONMOTION)) 522 | || (attr_id == 0xAD && (ven_id == ptr->SSD_VENDOR_TOSHIBA || ven_id == ptr->SSD_VENDOR_KIOXIA)) 523 | || (attr_id == 0xB1 && ven_id == ptr->SSD_VENDOR_SAMSUNG) 524 | || (attr_id == 0xBB && ven_id == ptr->SSD_VENDOR_MTRON) 525 | || (attr_id == 0xCA && (ven_id == ptr->SSD_VENDOR_MICRON || ven_id == ptr->SSD_VENDOR_MICRON_MU03 || ven_id == ptr->SSD_VENDOR_INTEL_DC || ven_id == ptr->SSD_VENDOR_SILICONMOTION_CVC)) 526 | || (attr_id == 0xD1 && ven_id == ptr->SSD_VENDOR_INDILINX) 527 | || (attr_id == 0xE7 && (ven_id == ptr->SSD_VENDOR_SANDFORCE || ven_id == ptr->SSD_VENDOR_CORSAIR || ven_id == ptr->SSD_VENDOR_KINGSTON || ven_id == ptr->SSD_VENDOR_SKHYNIX 528 | || ven_id == ptr->SSD_VENDOR_REALTEK || ven_id == ptr->SSD_VENDOR_SANDISK || ven_id == ptr->SSD_VENDOR_SSSTC || ven_id == ptr->SSD_VENDOR_APACER 529 | || ven_id == ptr->SSD_VENDOR_JMICRON || ven_id == ptr->SSD_VENDOR_SEAGATE || ven_id == ptr->SSD_VENDOR_MAXIOTEK 530 | || ven_id == ptr->SSD_VENDOR_YMTC || ven_id == ptr->SSD_VENDOR_SCY || ven_id == ptr->SSD_VENDOR_RECADATA || ven_id == ptr->SSD_VENDOR_ADATA_INDUSTRIAL)) 531 | || (attr_id == 0xE8 && ven_id == ptr->SSD_VENDOR_PLEXTOR) 532 | || (attr_id == 0xE9 && (ven_id == ptr->SSD_VENDOR_INTEL || ven_id == ptr->SSD_VENDOR_OCZ || ven_id == ptr->SSD_VENDOR_OCZ_VECTOR || ven_id == ptr->SSD_VENDOR_SKHYNIX)) 533 | || (attr_id == 0xE9 && ven_id == ptr->SSD_VENDOR_SANDISK_LENOVO_HELEN_VENUS) 534 | || (attr_id == 0xE6 && (ven_id == ptr->SSD_VENDOR_SANDISK_LENOVO || ven_id == ptr->SSD_VENDOR_SANDISK_DELL)) 535 | || (attr_id == 0xC9 && (ven_id == ptr->SSD_VENDOR_SANDISK_HP || ven_id == ptr->SSD_VENDOR_SANDISK_HP_VENUS)) 536 | ) 537 | { 538 | if (ptr->vars[index].FlagLifeRawValue || ptr->vars[index].FlagLifeRawValueIncrement) 539 | stat = CDI_DISK_STATUS_GOOD; 540 | else if (ptr->vars[index].Attribute[attr].CurrentValue == 0 541 | || ptr->vars[index].Attribute[attr].CurrentValue < ptr->vars[index].Threshold[attr].ThresholdValue) 542 | stat = CDI_DISK_STATUS_BAD; 543 | else if (ptr->vars[index].Attribute[attr].CurrentValue <= ptr->vars[index].ThresholdFF) 544 | stat = CDI_DISK_STATUS_CAUTION; 545 | else 546 | stat = CDI_DISK_STATUS_GOOD; 547 | } 548 | else if (attr_id == 0x01 // Read Error Rate for SandForce Bug 549 | && ven_id == ptr->SSD_VENDOR_SANDFORCE) 550 | { 551 | if (ptr->vars[index].Attribute[attr].CurrentValue == 0 552 | && ptr->vars[index].Attribute[attr].RawValue[0] == 0 553 | && ptr->vars[index].Attribute[attr].RawValue[1] == 0) 554 | stat = CDI_DISK_STATUS_GOOD; 555 | else if (ptr->vars[index].Threshold[attr].ThresholdValue 556 | && ptr->vars[index].Attribute[attr].CurrentValue < ptr->vars[index].Threshold[attr].ThresholdValue) 557 | stat = CDI_DISK_STATUS_BAD; 558 | else 559 | stat = CDI_DISK_STATUS_GOOD; 560 | } 561 | else if ((ptr->vars[index].IsSsd && !ptr->vars[index].IsRawValues8) 562 | || ((0x01 <= attr_id && attr_id <= 0x0D) 563 | || attr_id == 0x16 564 | || (0xBB <= attr_id && attr_id <= 0xC1) 565 | || (0xC3 <= attr_id && attr_id <= 0xD1) 566 | || (0xD3 <= attr_id && attr_id <= 0xD4) 567 | || (0xDC <= attr_id && attr_id <= 0xE4) 568 | || (0xE6 <= attr_id && attr_id <= 0xE7) 569 | || attr_id == 0xF0 570 | || attr_id == 0xFA 571 | || attr_id == 0xFE 572 | )) 573 | { 574 | if (ptr->vars[index].Threshold[attr].ThresholdValue 575 | && ptr->vars[index].Attribute[attr].CurrentValue < ptr->vars[index].Threshold[attr].ThresholdValue) 576 | stat = CDI_DISK_STATUS_BAD; 577 | else 578 | stat = CDI_DISK_STATUS_GOOD; 579 | } 580 | else 581 | stat = CDI_DISK_STATUS_GOOD; 582 | } 583 | 584 | return stat; 585 | } 586 | 587 | extern "C" WCHAR * WINAPI 588 | cdi_get_smart_name(CDI_SMART * ptr, INT index, BYTE id) 589 | { 590 | for (size_t i = 0; i < ARRAYSIZE(SMART_NAMES); i++) 591 | { 592 | if (ptr->vars[index].SmartKeyName.CompareNoCase(SMART_NAMES[i].group) == 0) 593 | { 594 | for (size_t j = 0; j < SMART_NAMES[i].count; j++) 595 | { 596 | if (id == SMART_NAMES[i].name[j].id) 597 | return cs_to_wcs(SMART_NAMES[i].name[j].name); 598 | } 599 | break; 600 | } 601 | } 602 | return cs_to_wcs(_T("Vendor Specific")); 603 | } 604 | -------------------------------------------------------------------------------- /libcdi/libcdi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define VC_EXTRALEAN 4 | #include 5 | 6 | enum CDI_ATA_BOOL 7 | { 8 | CDI_BOOL_SSD = 0, 9 | CDI_BOOL_SSD_NVME, 10 | CDI_BOOL_SMART, 11 | CDI_BOOL_LBA48, 12 | CDI_BOOL_AAM, 13 | CDI_BOOL_APM, 14 | CDI_BOOL_NCQ, 15 | CDI_BOOL_NV_CACHE, 16 | CDI_BOOL_DEVSLP, 17 | CDI_BOOL_STREAMING, 18 | CDI_BOOL_GPL, 19 | CDI_BOOL_TRIM, 20 | CDI_BOOL_VOLATILE_WRITE_CACHE, 21 | CDI_BOOL_SMART_ENABLED, 22 | CDI_BOOL_AAM_ENABLED, 23 | CDI_BOOL_APM_ENABLED, 24 | }; 25 | 26 | enum CDI_ATA_INT 27 | { 28 | CDI_INT_DISK_ID = 0, 29 | CDI_INT_DISK_STATUS, 30 | CDI_INT_SCSI_PORT, 31 | CDI_INT_SCSI_TARGET_ID, 32 | CDI_INT_SCSI_BUS, 33 | CDI_INT_POWER_ON_HOURS, 34 | CDI_INT_TEMPERATURE, 35 | CDI_INT_TEMPERATURE_ALARM, 36 | CDI_INT_HOST_WRITES, 37 | CDI_INT_HOST_READS, 38 | CDI_INT_NAND_WRITES, 39 | CDI_INT_GB_ERASED, 40 | CDI_INT_WEAR_LEVELING_COUNT, 41 | CDI_INT_LIFE, 42 | CDI_INT_MAX_ATTRIBUTE, 43 | }; 44 | 45 | enum CDI_ATA_DWORD 46 | { 47 | CDI_DWORD_DISK_SIZE = 0, 48 | CDI_DWORD_LOGICAL_SECTOR_SIZE, 49 | CDI_DWORD_PHYSICAL_SECTOR_SIZE, 50 | CDI_DWORD_BUFFER_SIZE, 51 | CDI_DWORD_ATTR_COUNT, 52 | CDI_DWORD_POWER_ON_COUNT, 53 | CDI_DWORD_ROTATION_RATE, 54 | CDI_DWORD_DRIVE_LETTER, 55 | CDI_DWORD_DISK_VENDOR_ID, // SSD_VENDOR_NVME = 19 56 | }; 57 | 58 | enum CDI_ATA_STRING 59 | { 60 | CDI_STRING_SN = 0, 61 | CDI_STRING_FIRMWARE, 62 | CDI_STRING_MODEL, 63 | CDI_STRING_DRIVE_MAP, 64 | CDI_STRING_TRANSFER_MODE_MAX, 65 | CDI_STRING_TRANSFER_MODE_CUR, 66 | CDI_STRING_INTERFACE, 67 | CDI_STRING_VERSION_MAJOR, 68 | CDI_STRING_VERSION_MINOR, 69 | CDI_STRING_PNP_ID, 70 | CDI_STRING_SMART_KEY, 71 | }; 72 | 73 | enum CDI_DISK_STATUS 74 | { 75 | CDI_DISK_STATUS_UNKNOWN = 0, 76 | CDI_DISK_STATUS_GOOD, 77 | CDI_DISK_STATUS_CAUTION, 78 | CDI_DISK_STATUS_BAD 79 | }; 80 | 81 | #define CDI_FLAG_USE_WMI (1ULL << 0) // TRUE 82 | #define CDI_FLAG_ADVANCED_SEARCH (1ULL << 1) // FALSE 83 | #define CDI_FLAG_WORKAROUND_HD204UI (1ULL << 2) // FALSE 84 | #define CDI_FLAG_WORKAROUND_ADATA (1ULL << 3) // FALSE 85 | #define CDI_FLAG_HIDE_NO_SMART (1ULL << 4) // FALSE 86 | #define CDI_FLAG_SORT_DRIVE_LETTER (1ULL << 5) // FALSE 87 | #define CDI_FLAG_NO_WAKEUP (1ULL << 6) // FALSE 88 | #define CDI_FLAG_ATA_PASS_THROUGH (1ULL << 7) // TRUE 89 | 90 | #define CDI_FLAG_ENABLE_NVIDIA (1ULL << 8) // TRUE 91 | #define CDI_FLAG_ENABLE_MARVELL (1ULL << 9) // TRUE 92 | #define CDI_FLAG_ENABLE_USB_SAT (1ULL << 10) // TRUE 93 | #define CDI_FLAG_ENABLE_USB_SUNPLUS (1ULL << 11) // TRUE 94 | #define CDI_FLAG_ENABLE_USB_IODATA (1ULL << 12) // TRUE 95 | #define CDI_FLAG_ENABLE_USB_LOGITEC (1ULL << 13) // TRUE 96 | #define CDI_FLAG_ENABLE_USB_PROLIFIC (1ULL << 14) // TRUE 97 | #define CDI_FLAG_ENABLE_USB_JMICRON (1ULL << 15) // TRUE 98 | #define CDI_FLAG_ENABLE_USB_CYPRESS (1ULL << 16) // TRUE 99 | #define CDI_FLAG_ENABLE_USB_MEMORY (1ULL << 17) // TRUE 100 | 101 | #define CDI_FLAG_ENABLE_NVME_JMICRON (1ULL << 19) // TRUE 102 | #define CDI_FLAG_ENABLE_NVME_ASMEDIA (1ULL << 20) // TRUE 103 | #define CDI_FLAG_ENABLE_NVME_REALTEK (1ULL << 21) // TRUE 104 | #define CDI_FLAG_ENABLE_MEGA_RAID (1ULL << 22) // TRUE 105 | #define CDI_FLAG_ENABLE_INTEL_VROC (1ULL << 23) // TRUE 106 | #define CDI_FLAG_ENABLE_ASM1352R (1ULL << 24) // TRUE 107 | #define CDI_FLAG_ENABLE_AMD_RC2 (1ULL << 25) // FALSE 108 | #define CDI_FLAG_ENABLE_REALTEK_9220DP (1ULL << 26) // FALSE 109 | 110 | #define CDI_FLAG_HIDE_RAID_VOLUME (1ULL << 27) // TRUE 111 | 112 | #define CDI_FLAG_DEFAULT \ 113 | ( \ 114 | CDI_FLAG_USE_WMI | \ 115 | CDI_FLAG_ATA_PASS_THROUGH | \ 116 | CDI_FLAG_ENABLE_NVIDIA | \ 117 | CDI_FLAG_ENABLE_MARVELL | \ 118 | CDI_FLAG_ENABLE_USB_SAT | \ 119 | CDI_FLAG_ENABLE_USB_SUNPLUS | \ 120 | CDI_FLAG_ENABLE_USB_IODATA | \ 121 | CDI_FLAG_ENABLE_USB_LOGITEC | \ 122 | CDI_FLAG_ENABLE_USB_PROLIFIC | \ 123 | CDI_FLAG_ENABLE_USB_JMICRON | \ 124 | CDI_FLAG_ENABLE_USB_CYPRESS | \ 125 | CDI_FLAG_ENABLE_USB_MEMORY | \ 126 | CDI_FLAG_ENABLE_NVME_JMICRON | \ 127 | CDI_FLAG_ENABLE_NVME_ASMEDIA | \ 128 | CDI_FLAG_ENABLE_NVME_REALTEK | \ 129 | CDI_FLAG_ENABLE_MEGA_RAID | \ 130 | CDI_FLAG_ENABLE_INTEL_VROC | \ 131 | CDI_FLAG_ENABLE_ASM1352R | \ 132 | CDI_FLAG_HIDE_RAID_VOLUME \ 133 | ) 134 | 135 | #ifdef LIBCDI_IMPLEMENTATION 136 | typedef CAtaSmart CDI_SMART; 137 | #else 138 | typedef struct _CDI_SMART CDI_SMART; 139 | #endif 140 | 141 | #ifdef __cplusplus 142 | extern "C" { 143 | #endif 144 | 145 | CONST CHAR* WINAPI cdi_get_version(VOID); 146 | 147 | CDI_SMART* WINAPI cdi_create_smart(VOID); 148 | VOID WINAPI cdi_destroy_smart(CDI_SMART* ptr); 149 | VOID WINAPI cdi_init_smart(CDI_SMART* ptr, UINT64 flags); 150 | DWORD WINAPI cdi_update_smart(CDI_SMART* ptr, INT index); 151 | INT WINAPI cdi_get_disk_count(CDI_SMART* ptr); 152 | 153 | BOOL WINAPI cdi_get_bool(CDI_SMART* ptr, INT index, enum CDI_ATA_BOOL attr); 154 | INT WINAPI cdi_get_int(CDI_SMART* ptr, INT index, enum CDI_ATA_INT attr); 155 | DWORD WINAPI cdi_get_dword(CDI_SMART* ptr, INT index, enum CDI_ATA_DWORD attr); 156 | WCHAR* WINAPI cdi_get_string(CDI_SMART* ptr, INT index, enum CDI_ATA_STRING attr); 157 | VOID WINAPI cdi_free_string(WCHAR* ptr); 158 | 159 | WCHAR* WINAPI cdi_get_smart_format(CDI_SMART* ptr, INT index); 160 | BYTE WINAPI cdi_get_smart_id(CDI_SMART* ptr, INT index, INT attr); 161 | WCHAR* WINAPI cdi_get_smart_value(CDI_SMART* ptr, INT index, INT attr, BOOL hex); 162 | INT WINAPI cdi_get_smart_status(CDI_SMART* ptr, INT index, INT attr); 163 | WCHAR* WINAPI cdi_get_smart_name(CDI_SMART* ptr, INT index, BYTE id); 164 | 165 | static inline LPCSTR 166 | cdi_get_health_status(enum CDI_DISK_STATUS status) 167 | { 168 | switch (status) 169 | { 170 | case CDI_DISK_STATUS_GOOD: 171 | return "Good"; 172 | case CDI_DISK_STATUS_CAUTION: 173 | return "Caution"; 174 | case CDI_DISK_STATUS_BAD: 175 | return "Bad"; 176 | } 177 | return "Unknown"; 178 | } 179 | 180 | #ifdef __cplusplus 181 | } 182 | #endif 183 | -------------------------------------------------------------------------------- /libcdi/libcdi.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Release 8 | ARM64 9 | 10 | 11 | Release 12 | Win32 13 | 14 | 15 | Release 16 | x64 17 | 18 | 19 | 20 | 16.0 21 | Win32Proj 22 | {f8c0b390-95be-4b12-ba9b-48b4774fdde4} 23 | libcdi 24 | 10.0 25 | 26 | 27 | 28 | DynamicLibrary 29 | false 30 | v143 31 | true 32 | Unicode 33 | true 34 | true 35 | true 36 | 5.1.2600.0 37 | YY_Thunks_for_WinXP.obj 38 | 39 | 40 | DynamicLibrary 41 | false 42 | v143 43 | true 44 | Unicode 45 | true 46 | true 47 | true 48 | 5.1.2600.0 49 | YY_Thunks_for_WinXP.obj 50 | 51 | 52 | DynamicLibrary 53 | false 54 | v143 55 | true 56 | Unicode 57 | true 58 | true 59 | true 60 | 10.0.10240.0 61 | YY_Thunks_for_Win10.0.10240.obj 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | $(SolutionDir)$(Platform)\$(Configuration)\ 80 | $(Platform)\$(Configuration)\ 81 | 82 | 83 | $(Platform)\$(Configuration)\ 84 | $(SolutionDir)$(Platform)\$(Configuration)\ 85 | 86 | 87 | $(Platform)\$(Configuration)\ 88 | $(SolutionDir)$(Platform)\$(Configuration)\ 89 | 90 | 91 | 92 | Level3 93 | true 94 | true 95 | true 96 | WIN32;NDEBUG;_WINDOWS;_USRDLL;JMICRON_USB_RAID_SUPPORT;%(PreprocessorDefinitions) 97 | true 98 | stdcpp20 99 | stdc17 100 | $(ProjectDir)Priscilla\;%(AdditionalIncludeDirectories) 101 | true 102 | MultiThreaded 103 | 104 | 105 | Console 106 | true 107 | true 108 | true 109 | Source.def 110 | 111 | 112 | 113 | 114 | Level3 115 | true 116 | true 117 | true 118 | NDEBUG;_WINDOWS;_USRDLL;JMICRON_USB_RAID_SUPPORT;%(PreprocessorDefinitions) 119 | true 120 | stdcpp20 121 | stdc17 122 | $(ProjectDir)Priscilla\;%(AdditionalIncludeDirectories) 123 | true 124 | MultiThreaded 125 | 126 | 127 | Console 128 | true 129 | true 130 | true 131 | Source.def 132 | 133 | 134 | 135 | 136 | Level3 137 | true 138 | true 139 | true 140 | NDEBUG;_WINDOWS;_USRDLL;JMICRON_USB_RAID_SUPPORT;%(PreprocessorDefinitions) 141 | true 142 | stdcpp20 143 | stdc17 144 | $(ProjectDir)Priscilla\;%(AdditionalIncludeDirectories) 145 | true 146 | MultiThreaded 147 | 148 | 149 | Console 150 | true 151 | true 152 | true 153 | Source.def 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 200 | 201 | 202 | 203 | 204 | 205 | 206 | -------------------------------------------------------------------------------- /libcdi/libcdi.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 6 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 7 | 8 | 9 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 10 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Sources 20 | 21 | 22 | Sources 23 | 24 | 25 | Sources 26 | 27 | 28 | Sources 29 | 30 | 31 | Sources 32 | 33 | 34 | Sources 35 | 36 | 37 | Sources 38 | 39 | 40 | 41 | 42 | Headers 43 | 44 | 45 | Headers 46 | 47 | 48 | Headers 49 | 50 | 51 | Headers 52 | 53 | 54 | Headers 55 | 56 | 57 | Headers 58 | 59 | 60 | Headers 61 | 62 | 63 | Headers 64 | 65 | 66 | Headers 67 | 68 | 69 | Headers 70 | 71 | 72 | Headers 73 | 74 | 75 | Headers 76 | 77 | 78 | Headers 79 | 80 | 81 | Headers 82 | 83 | 84 | Headers 85 | 86 | 87 | 88 | 89 | Sources 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | RC 99 | 100 | 101 | -------------------------------------------------------------------------------- /libcdi/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /libcdi/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // 3 | 4 | // Next default values for new objects 5 | // 6 | #ifdef APSTUDIO_INVOKED 7 | #ifndef APSTUDIO_READONLY_SYMBOLS 8 | #define _APS_NEXT_RESOURCE_VALUE 102 9 | #define _APS_NEXT_COMMAND_VALUE 40001 10 | #define _APS_NEXT_CONTROL_VALUE 1001 11 | #define _APS_NEXT_SYMED_VALUE 101 12 | #endif 13 | #endif 14 | -------------------------------------------------------------------------------- /libcdi/stdafx.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*/ 2 | // Author : hiyohiyo 3 | // Mail : hiyohiyo@crystalmark.info 4 | // Web : https://crystalmark.info/ 5 | // License : MIT License 6 | /*---------------------------------------------------------------------------*/ 7 | 8 | #pragma once 9 | 10 | #ifndef _SECURE_ATL 11 | #define _SECURE_ATL 1 12 | #endif 13 | 14 | #ifndef VC_EXTRALEAN 15 | #define VC_EXTRALEAN 16 | #endif 17 | 18 | #ifndef WINVER 19 | #define WINVER 0x0501 20 | #endif 21 | 22 | #ifndef _WIN32_WINNT 23 | #define _WIN32_WINNT 0x0501 24 | #endif 25 | 26 | #ifndef _WIN32_WINDOWS 27 | #define _WIN32_WINDOWS 0x0410 28 | #endif 29 | 30 | #ifndef _WIN32_IE 31 | #define _WIN32_IE 0x0600 32 | #endif 33 | 34 | #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS 35 | #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS 36 | #define _AFX_ALL_WARNINGS 37 | 38 | #include // MFC core and standard component 39 | 40 | #include 41 | 42 | #define CERTNAME_JMS56X L"Open Source Developer, Noriyuki Miyazaki" 43 | #define CERTNAME_JMB39X L"Open Source Developer, Noriyuki Miyazaki" 44 | #define CERTNAME_JMS586_20 L"Open Source Developer, Noriyuki Miyazaki" 45 | #define CERTNAME_JMS586_40 L"Open Source Developer, Noriyuki Miyazaki" 46 | -------------------------------------------------------------------------------- /libcdi/version.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Unlicense 2 | 3 | #pragma once 4 | 5 | #define QUOTE_(x) #x 6 | #define QUOTE(x) QUOTE_(x) 7 | 8 | #define LIBCDI_MAJOR_VERSION 9 9 | #define LIBCDI_MINOR_VERSION 7 10 | #define LIBCDI_MICRO_VERSION 0 11 | #define LIBCDI_BUILD_VERSION 0 12 | 13 | #define LIBCDI_VERSION LIBCDI_MAJOR_VERSION,LIBCDI_MINOR_VERSION,LIBCDI_MICRO_VERSION,LIBCDI_BUILD_VERSION 14 | #define LIBCDI_VERSION_STR QUOTE(LIBCDI_MAJOR_VERSION.LIBCDI_MINOR_VERSION.LIBCDI_MICRO_VERSION.LIBCDI_BUILD_VERSION) 15 | 16 | #define LIBCDI_COMPANY "A1ive" 17 | #define LIBCDI_COPYRIGHT "(C) 2025 A1ive, (C) 2008-2025 hiyohiyo" 18 | #define LIBCDI_FILEDESC "CrystalDiskInfo DLL" 19 | 20 | #define LIBCDI_DLL "libcdi" 21 | 22 | --------------------------------------------------------------------------------