deadbyte-mcp 0.15.74 → 0.15.76

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/MANIFEST.SHA256 +108 -42
  2. package/PROVENANCE.json +20 -22
  3. package/README.txt +23 -18
  4. package/RELEASE.json +69 -18
  5. package/SBOM.cdx.json +2 -2
  6. package/TEST-MATRIX.json +32 -2
  7. package/bin/deadbyte-desktop-uia-r199-fixed.exe +0 -0
  8. package/bin/deadbyte-desktop-uia-r199-fixed.obj +0 -0
  9. package/bin/deadbyte-desktop-uia-r199.exe +0 -0
  10. package/bin/deadbyte-desktop-uia-r199.obj +0 -0
  11. package/bin/deadbyte-fs-read-r197-fixed.exe +0 -0
  12. package/bin/deadbyte-fs-read-r198.exe +0 -0
  13. package/bin/deadbyte-fs-read-r198.obj +0 -0
  14. package/bin/deadbyte-root-relative-probe-r197.exe +0 -0
  15. package/bridge/package.json +1 -1
  16. package/controller/deadbyte-process-policy.json +4 -4
  17. package/docs/R184-package-lock.json +2 -8
  18. package/native/deadbyte-desktop-uia-r199.cpp +345 -0
  19. package/native/deadbyte-fs-read-r197.cpp +174 -0
  20. package/native/deadbyte-fs-read-r198.cpp +181 -0
  21. package/native/deadbyte-root-relative-probe-r197.cpp +97 -0
  22. package/package.json +5 -2
  23. package/scripts/build-native-desktop-uia-r199-fixed.ps1 +28 -0
  24. package/scripts/build-native-desktop-uia-r199.ps1 +28 -0
  25. package/scripts/build-native-fs-read-r197-fixed.ps1 +28 -0
  26. package/scripts/build-native-fs-read-r197.ps1 +28 -0
  27. package/scripts/build-native-fs-read-r198.ps1 +28 -0
  28. package/scripts/build-native-root-probe-r197.ps1 +28 -0
  29. package/scripts/gate-windows-r195.ps1 +114 -0
  30. package/scripts/gate-windows-r206.ps1 +116 -0
  31. package/scripts/gate-windows-r207.ps1 +104 -0
  32. package/scripts/init-desktop-policy-r199.ps1 +85 -0
  33. package/scripts/npm-release-r48.mjs +27 -0
  34. package/scripts/npm-release-readiness-r195.mjs +72 -0
  35. package/scripts/npm-release-readiness-r206.mjs +76 -0
  36. package/scripts/npm-release-readiness-r207.mjs +76 -0
  37. package/scripts/r193-owner-request-live.mjs +8 -7
  38. package/scripts/r193-owner-uac-broker.mjs +6 -5
  39. package/scripts/r205-candidate-selection.mjs +22 -0
  40. package/src/candidate-selection-evidence-r206.mjs +71 -0
  41. package/src/candidate-selection-r205.mjs +96 -0
  42. package/src/desktop-postcondition-r196.mjs +30 -0
  43. package/src/desktop-runtime-r40.mjs +44 -7
  44. package/src/desktop-uia-identity-r199.mjs +51 -0
  45. package/src/desktop-uia-r40.mjs +9 -1
  46. package/src/machine-fs-handle-read-r196.mjs +43 -0
  47. package/src/machine-fs-native-read-r197.mjs +73 -0
  48. package/src/machine-fs-native-read-r198.mjs +76 -0
  49. package/src/machine-fs-read-worker.mjs +5 -25
  50. package/src/machine-fs.mjs +31 -16
  51. package/src/r195-canonical-owner-observation.mjs +15 -0
  52. package/src/r207-owner-enrollment-io.mjs +30 -0
  53. package/src/remote-destination-journal-r202.mjs +120 -0
  54. package/src/remote-device-r44.mjs +89 -14
  55. package/src/remote-payload-boundary-r201.mjs +71 -0
  56. package/src/remote-terminal-evidence-r200.mjs +60 -0
  57. package/src/version.mjs +1 -1
  58. package/test/desktop-runtime-r40.test.mjs +111 -0
  59. package/test/desktop-uia-r40.test.mjs +15 -0
  60. package/test/fixtures/r197-junction-swap-worker.mjs +21 -0
  61. package/test/fixtures/r203-journal-writer.mjs +6 -0
  62. package/test/process-policy-refresh.test.mjs +4 -4
  63. package/test/r130-release-security-contract.test.mjs +8 -8
  64. package/test/r132-release-identity.test.mjs +7 -7
  65. package/test/r153-prepublish-identity.test.mjs +1 -1
  66. package/test/r160-release-contract.test.mjs +3 -3
  67. package/test/r165-live-cli-skew.test.mjs +1 -1
  68. package/test/r167-release-contract.test.mjs +11 -11
  69. package/test/r168-release-contract.test.mjs +4 -4
  70. package/test/r172-release-contract.test.mjs +6 -6
  71. package/test/r173-release-contract.test.mjs +16 -16
  72. package/test/r179-release-contract.test.mjs +12 -12
  73. package/test/r190-release-contract.test.mjs +10 -10
  74. package/test/r191-release-contract.test.mjs +12 -12
  75. package/test/r192-release-identity.test.mjs +9 -9
  76. package/test/r193-release-identity.test.mjs +24 -22
  77. package/test/r193-release-readiness.test.mjs +2 -2
  78. package/test/r193-windows-gate.test.mjs +10 -10
  79. package/test/r194-release-identity.test.mjs +19 -15
  80. package/test/r194-release-readiness.test.mjs +3 -3
  81. package/test/r194-windows-gate.test.mjs +9 -8
  82. package/test/r195-canonical-owner-observation.test.mjs +32 -0
  83. package/test/r195-release-readiness.test.mjs +22 -0
  84. package/test/r196-desktop-postcondition.test.mjs +53 -0
  85. package/test/r196-handle-bound-read.test.mjs +99 -0
  86. package/test/r196-remote-outcome.test.mjs +94 -0
  87. package/test/r197-namespace-race.test.mjs +41 -0
  88. package/test/r197-native-dispatch-race.test.mjs +49 -0
  89. package/test/r197-native-file-read.test.mjs +60 -0
  90. package/test/r197-native-root-open.test.mjs +61 -0
  91. package/test/r198-root-identity.test.mjs +88 -0
  92. package/test/r199-native-uia-worker.test.mjs +28 -0
  93. package/test/r199-uia-identity.test.mjs +43 -0
  94. package/test/r200-remote-reconcile.test.mjs +106 -0
  95. package/test/r201-payload-boundary.test.mjs +78 -0
  96. package/test/r201-payload-fuzz.test.mjs +37 -0
  97. package/test/r201-tool-boundary-fuzz.test.mjs +120 -0
  98. package/test/r202-destination-journal.test.mjs +92 -0
  99. package/test/r203-atomic-journal.test.mjs +86 -0
  100. package/test/r205-candidate-selection-cli.test.mjs +31 -0
  101. package/test/r205-candidate-selection.test.mjs +83 -0
  102. package/test/r206-candidate-evidence.test.mjs +64 -0
  103. package/test/r206-release-contract.test.mjs +42 -0
  104. package/test/r206-release-readiness.test.mjs +23 -0
  105. package/test/r207-owner-enrollment-io.test.mjs +37 -0
  106. package/test/r207-release-contract.test.mjs +51 -0
  107. package/test/r207-release-readiness.test.mjs +23 -0
  108. package/test/r59-tool-surface-compat.test.mjs +1 -1
  109. package/test/r64-machine-fs-large-read.test.mjs +26 -12
@@ -0,0 +1,174 @@
1
+ #define WIN32_LEAN_AND_MEAN
2
+ #define NOMINMAX
3
+ #include <windows.h>
4
+ #include <winternl.h>
5
+ #include <bcrypt.h>
6
+ #include <cstdio>
7
+ #include <cstdlib>
8
+ #include <cstring>
9
+ #include <cwchar>
10
+ #include <string>
11
+ #include <vector>
12
+ #include <algorithm>
13
+ #pragma comment(lib, "bcrypt.lib")
14
+
15
+ // A Windows-only experimental reader. Kernel resolution is anchored to an
16
+ // already-open directory HANDLE. No reparse component is followed.
17
+ // The caller must supply the independently authorized root and relative path.
18
+ // This file is not a release authorization or production deployment.
19
+ using NtCreateFilePtr=NTSTATUS (NTAPI *)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,
20
+ PIO_STATUS_BLOCK,PLARGE_INTEGER,ULONG,ULONG,ULONG,ULONG,PVOID,ULONG);
21
+ static constexpr ULONG kFileOpen=1, kFileDir=0x1, kFileNotDir=0x40;
22
+ static constexpr ULONG kFileSync=0x20, kFileNoReparse=0x00200000, kObjNoReparse=0x1000;
23
+ static void fail(const char* m,int exitCode=2){
24
+ std::fprintf(stderr,"R197_NATIVE_REFUSE=%s\n",m);std::exit(exitCode);
25
+ }
26
+ static bool noReparse(HANDLE h){
27
+ FILE_ATTRIBUTE_TAG_INFO t{};
28
+ return GetFileInformationByHandleEx(h,FileAttributeTagInfo,&t,sizeof(t)) &&
29
+ (t.FileAttributes&FILE_ATTRIBUTE_REPARSE_POINT)==0;
30
+ }
31
+ static unsigned long long parseNumber(const wchar_t* input){
32
+ if(!input||!*input)fail("missing_number");
33
+ for(const wchar_t* q=input;*q;++q)if(*q<L'0'||*q>L'9')fail("invalid_number");
34
+ wchar_t* end=nullptr;
35
+ errno=0;
36
+ const auto n=std::wcstoull(input,&end,10);
37
+ if(errno||!end||*end!=L'\0')fail("number_overflow");
38
+ return n;
39
+ }
40
+ static std::vector<std::wstring> split(const std::wstring& rel){
41
+ if(rel.empty()||rel.size()>1024||rel[0]==L'\\'||rel[0]==L'/'||rel.find(L':')!=std::wstring::npos)
42
+ fail("invalid_relative_path");
43
+ std::vector<std::wstring> result;size_t start=0;
44
+ for(size_t i=0;i<=rel.size();++i){
45
+ if(i==rel.size()||rel[i]==L'/'||rel[i]==L'\\'){
46
+ const auto s=rel.substr(start,i-start);
47
+ if(s.empty()||s==L"."||s==L".."||s.size()>255||s.back()==L'.'||s.back()==L' '||
48
+ s.find(L'\0')!=std::wstring::npos)fail("invalid_segment");
49
+ result.push_back(s);start=i+1;
50
+ }
51
+ }
52
+ if(result.empty()||result.size()>32)fail("segment_budget");
53
+ return result;
54
+ }
55
+ static std::string base64(const unsigned char* b,size_t n){
56
+ static constexpr char abc[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
57
+ std::string out;out.reserve(((n+2)/3)*4);
58
+ for(size_t i=0;i<n;i+=3){
59
+ const unsigned a=b[i],x=i+1<n?b[i+1]:0,y=i+2<n?b[i+2]:0;
60
+ out.push_back(abc[a>>2]);out.push_back(abc[((a&3)<<4)|(x>>4)]);
61
+ out.push_back(i+1<n?abc[((x&15)<<2)|(y>>6)]:'=');
62
+ out.push_back(i+2<n?abc[y&63]:'=');
63
+ }
64
+ return out;
65
+ }
66
+ static std::string hex(const unsigned char* b,size_t n){
67
+ static constexpr char chars[]="0123456789abcdef";
68
+ std::string out;out.reserve(n*2);
69
+ for(size_t i=0;i<n;++i){out.push_back(chars[b[i]>>4]);out.push_back(chars[b[i]&15]);}
70
+ return out;
71
+ }
72
+ static void seek(HANDLE h,unsigned long long pos){
73
+ LARGE_INTEGER p{};p.QuadPart=static_cast<LONGLONG>(pos);
74
+ if(!SetFilePointerEx(h,p,nullptr,FILE_BEGIN))fail("seek_failed");
75
+ }
76
+ static std::string hashAll(HANDLE h){
77
+ BCRYPT_ALG_HANDLE algorithm=nullptr;BCRYPT_HASH_HANDLE hash=nullptr;
78
+ if(BCryptOpenAlgorithmProvider(&algorithm,BCRYPT_SHA256_ALGORITHM,nullptr,0)<0)fail("hash_alg");
79
+ if(BCryptCreateHash(algorithm,&hash,nullptr,0,nullptr,0,0)<0)fail("hash_create");
80
+ seek(h,0);
81
+ std::vector<unsigned char> buffer(65536);
82
+ DWORD got=0;
83
+ for(;;){
84
+ if(!ReadFile(h,buffer.data(),static_cast<DWORD>(buffer.size()),&got,nullptr))fail("hash_read");
85
+ if(got==0)break;
86
+ if(BCryptHashData(hash,buffer.data(),got,0)<0)fail("hash_update");
87
+ }
88
+ unsigned char sum[32]{};
89
+ if(BCryptFinishHash(hash,sum,sizeof(sum),0)<0)fail("hash_finish");
90
+ BCryptDestroyHash(hash);BCryptCloseAlgorithmProvider(algorithm,0);
91
+ return hex(sum,sizeof(sum));
92
+ }
93
+ int wmain(int argc,wchar_t** argv){
94
+ if(argc!=6)fail("usage_root_relative_offset_length_hash");
95
+ const std::wstring root=argv[1];
96
+ if(root.size()<4||root.size()>2048||root[1]!=L':'||(root[2]!=L'\\'&&root[2]!=L'/'))
97
+ fail("root_must_be_absolute_drive_path");
98
+ const auto names=split(argv[2]);
99
+ const auto offset=parseNumber(argv[3]),requested=parseNumber(argv[4]);
100
+ if(requested>4*1024*1024ULL||offset>9007199254740991ULL)fail("range_budget");
101
+ if(std::wcscmp(argv[5],L"0")!=0&&std::wcscmp(argv[5],L"1")!=0)fail("invalid_hash_mode");
102
+ const bool wantHash=argv[5][0]==L'1';
103
+ const HANDLE rootHandle=CreateFileW(root.c_str(),FILE_READ_ATTRIBUTES|FILE_LIST_DIRECTORY|SYNCHRONIZE,
104
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,nullptr,OPEN_EXISTING,
105
+ FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OPEN_REPARSE_POINT,nullptr);
106
+ if(rootHandle==INVALID_HANDLE_VALUE)fail("open_root");
107
+ if(!noReparse(rootHandle))fail("root_reparse_or_unverified");
108
+ FILE_ID_INFO rootId{};if(!GetFileInformationByHandleEx(rootHandle,FileIdInfo,&rootId,sizeof(rootId)))
109
+ fail("root_identity_unavailable");
110
+ HMODULE ntdll=GetModuleHandleW(L"ntdll.dll");
111
+ auto nt=reinterpret_cast<NtCreateFilePtr>(GetProcAddress(ntdll,"NtCreateFile"));
112
+ if(!nt)fail("ntcreatefile_unavailable");
113
+ HANDLE parent=rootHandle;std::vector<HANDLE> chain;chain.reserve(names.size());
114
+ for(size_t i=0;i<names.size();++i){
115
+ const bool dir=i+1<names.size();
116
+ UNICODE_STRING name{};name.Buffer=const_cast<PWSTR>(names[i].c_str());
117
+ name.Length=static_cast<USHORT>(names[i].size()*sizeof(wchar_t));
118
+ name.MaximumLength=name.Length;
119
+ OBJECT_ATTRIBUTES oa{};oa.Length=sizeof(oa);oa.RootDirectory=parent;
120
+ oa.ObjectName=&name;oa.Attributes=OBJ_CASE_INSENSITIVE|kObjNoReparse;
121
+ IO_STATUS_BLOCK ios{};HANDLE next=nullptr;
122
+ const ULONG options=kFileSync|kFileNoReparse|(dir?kFileDir:kFileNotDir);
123
+ const ACCESS_MASK access=FILE_READ_ATTRIBUTES|SYNCHRONIZE|(dir?FILE_LIST_DIRECTORY:FILE_READ_DATA);
124
+ const NTSTATUS status=nt(&next,access,&oa,&ios,nullptr,FILE_ATTRIBUTE_NORMAL,
125
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,kFileOpen,options,nullptr,0);
126
+ if(status<0||!next)fail("nt_open_component_refused",3);
127
+ chain.push_back(next);
128
+ if(!noReparse(next))fail("component_reparse_or_unverified",4);
129
+ FILE_ID_INFO id{};if(!GetFileInformationByHandleEx(next,FileIdInfo,&id,sizeof(id)))
130
+ fail("component_identity_unavailable",5);
131
+ parent=next;
132
+ }
133
+ const HANDLE leaf=chain.back();
134
+ FILE_ID_INFO identity{};
135
+ FILE_BASIC_INFO initialBasic{},finalBasic{};
136
+ FILE_STANDARD_INFO initialStandard{},finalStandard{};
137
+ if(!GetFileInformationByHandleEx(leaf,FileIdInfo,&identity,sizeof(identity)) ||
138
+ !GetFileInformationByHandleEx(leaf,FileBasicInfo,&initialBasic,sizeof(initialBasic)) ||
139
+ !GetFileInformationByHandleEx(leaf,FileStandardInfo,&initialStandard,sizeof(initialStandard)))
140
+ fail("file_identity_unavailable");
141
+ const auto fileSize=initialStandard.EndOfFile.QuadPart;
142
+ if(fileSize<0||fileSize>9007199254740991LL)fail("file_size_out_of_range");
143
+ if(offset>static_cast<unsigned long long>(fileSize))fail("offset_exceeds_size");
144
+ const auto length=static_cast<size_t>(std::min(requested,static_cast<unsigned long long>(fileSize)-offset));
145
+ std::vector<unsigned char> data(length);
146
+ seek(leaf,offset);
147
+ size_t read=0;
148
+ while(read<length){
149
+ DWORD got=0;
150
+ if(!ReadFile(leaf,data.data()+read,static_cast<DWORD>(length-read),&got,nullptr))
151
+ fail("range_read_failed");
152
+ if(got==0)fail("unexpected_range_eof");
153
+ read+=got;
154
+ }
155
+ const auto digest=wantHash?hashAll(leaf):std::string();
156
+ if(!GetFileInformationByHandleEx(leaf,FileBasicInfo,&finalBasic,sizeof(finalBasic))||
157
+ !GetFileInformationByHandleEx(leaf,FileStandardInfo,&finalStandard,sizeof(finalStandard)))
158
+ fail("file_postidentity_unavailable");
159
+ if(initialStandard.EndOfFile.QuadPart!=finalStandard.EndOfFile.QuadPart||
160
+ initialBasic.LastWriteTime.QuadPart!=finalBasic.LastWriteTime.QuadPart||
161
+ initialBasic.ChangeTime.QuadPart!=finalBasic.ChangeTime.QuadPart)
162
+ fail("file_mutated_during_read");
163
+ unsigned long long nativeId=0;
164
+ std::memcpy(&nativeId,identity.FileId.Identifier,sizeof(nativeId));
165
+ const auto encoded=base64(data.data(),data.size());
166
+ std::printf("{\"schema\":\"deadbyte.machine-fs-read-worker.v1\",\"bytes_read\":%llu,\"data_base64\":\"%s\",\"file_sha256\":",
167
+ static_cast<unsigned long long>(read),encoded.c_str());
168
+ if(wantHash)std::printf("\"%s\"",digest.c_str());else std::printf("null");
169
+ std::printf(",\"file_size\":%llu,\"file_dev\":\"%llu\",\"file_ino\":\"%llu\"}",
170
+ static_cast<unsigned long long>(fileSize),
171
+ static_cast<unsigned long long>(identity.VolumeSerialNumber & 0xffffffffULL),nativeId);
172
+ for(auto it=chain.rbegin();it!=chain.rend();++it)CloseHandle(*it);
173
+ CloseHandle(rootHandle);return 0;
174
+ }
@@ -0,0 +1,181 @@
1
+ #define WIN32_LEAN_AND_MEAN
2
+ #define NOMINMAX
3
+ #include <windows.h>
4
+ #include <winternl.h>
5
+ #include <bcrypt.h>
6
+ #include <cstdio>
7
+ #include <cstdlib>
8
+ #include <cstring>
9
+ #include <cwchar>
10
+ #include <string>
11
+ #include <vector>
12
+ #include <algorithm>
13
+ #pragma comment(lib, "bcrypt.lib")
14
+
15
+ // A Windows-only experimental reader. Kernel resolution is anchored to an
16
+ // already-open directory HANDLE. No reparse component is followed.
17
+ // The caller must supply the independently authorized root and relative path.
18
+ // This file is not a release authorization or production deployment.
19
+ using NtCreateFilePtr=NTSTATUS (NTAPI *)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,
20
+ PIO_STATUS_BLOCK,PLARGE_INTEGER,ULONG,ULONG,ULONG,ULONG,PVOID,ULONG);
21
+ static constexpr ULONG kFileOpen=1, kFileDir=0x1, kFileNotDir=0x40;
22
+ static constexpr ULONG kFileSync=0x20, kFileNoReparse=0x00200000, kObjNoReparse=0x1000;
23
+ static void fail(const char* m,int exitCode=2){
24
+ std::fprintf(stderr,"R197_NATIVE_REFUSE=%s\n",m);std::exit(exitCode);
25
+ }
26
+ static bool noReparse(HANDLE h){
27
+ FILE_ATTRIBUTE_TAG_INFO t{};
28
+ return GetFileInformationByHandleEx(h,FileAttributeTagInfo,&t,sizeof(t)) &&
29
+ (t.FileAttributes&FILE_ATTRIBUTE_REPARSE_POINT)==0;
30
+ }
31
+ static unsigned long long parseNumber(const wchar_t* input){
32
+ if(!input||!*input)fail("missing_number");
33
+ for(const wchar_t* q=input;*q;++q)if(*q<L'0'||*q>L'9')fail("invalid_number");
34
+ wchar_t* end=nullptr;
35
+ errno=0;
36
+ const auto n=std::wcstoull(input,&end,10);
37
+ if(errno||!end||*end!=L'\0')fail("number_overflow");
38
+ return n;
39
+ }
40
+ static std::vector<std::wstring> split(const std::wstring& rel){
41
+ if(rel.empty()||rel.size()>1024||rel[0]==L'\\'||rel[0]==L'/'||rel.find(L':')!=std::wstring::npos)
42
+ fail("invalid_relative_path");
43
+ std::vector<std::wstring> result;size_t start=0;
44
+ for(size_t i=0;i<=rel.size();++i){
45
+ if(i==rel.size()||rel[i]==L'/'||rel[i]==L'\\'){
46
+ const auto s=rel.substr(start,i-start);
47
+ if(s.empty()||s==L"."||s==L".."||s.size()>255||s.back()==L'.'||s.back()==L' '||
48
+ s.find(L'\0')!=std::wstring::npos)fail("invalid_segment");
49
+ result.push_back(s);start=i+1;
50
+ }
51
+ }
52
+ if(result.empty()||result.size()>32)fail("segment_budget");
53
+ return result;
54
+ }
55
+ static std::string base64(const unsigned char* b,size_t n){
56
+ static constexpr char abc[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
57
+ std::string out;out.reserve(((n+2)/3)*4);
58
+ for(size_t i=0;i<n;i+=3){
59
+ const unsigned a=b[i],x=i+1<n?b[i+1]:0,y=i+2<n?b[i+2]:0;
60
+ out.push_back(abc[a>>2]);out.push_back(abc[((a&3)<<4)|(x>>4)]);
61
+ out.push_back(i+1<n?abc[((x&15)<<2)|(y>>6)]:'=');
62
+ out.push_back(i+2<n?abc[y&63]:'=');
63
+ }
64
+ return out;
65
+ }
66
+ static std::string hex(const unsigned char* b,size_t n){
67
+ static constexpr char chars[]="0123456789abcdef";
68
+ std::string out;out.reserve(n*2);
69
+ for(size_t i=0;i<n;++i){out.push_back(chars[b[i]>>4]);out.push_back(chars[b[i]&15]);}
70
+ return out;
71
+ }
72
+ static void seek(HANDLE h,unsigned long long pos){
73
+ LARGE_INTEGER p{};p.QuadPart=static_cast<LONGLONG>(pos);
74
+ if(!SetFilePointerEx(h,p,nullptr,FILE_BEGIN))fail("seek_failed");
75
+ }
76
+ static std::string hashAll(HANDLE h){
77
+ BCRYPT_ALG_HANDLE algorithm=nullptr;BCRYPT_HASH_HANDLE hash=nullptr;
78
+ if(BCryptOpenAlgorithmProvider(&algorithm,BCRYPT_SHA256_ALGORITHM,nullptr,0)<0)fail("hash_alg");
79
+ if(BCryptCreateHash(algorithm,&hash,nullptr,0,nullptr,0,0)<0)fail("hash_create");
80
+ seek(h,0);
81
+ std::vector<unsigned char> buffer(65536);
82
+ DWORD got=0;
83
+ for(;;){
84
+ if(!ReadFile(h,buffer.data(),static_cast<DWORD>(buffer.size()),&got,nullptr))fail("hash_read");
85
+ if(got==0)break;
86
+ if(BCryptHashData(hash,buffer.data(),got,0)<0)fail("hash_update");
87
+ }
88
+ unsigned char sum[32]{};
89
+ if(BCryptFinishHash(hash,sum,sizeof(sum),0)<0)fail("hash_finish");
90
+ BCryptDestroyHash(hash);BCryptCloseAlgorithmProvider(algorithm,0);
91
+ return hex(sum,sizeof(sum));
92
+ }
93
+ int wmain(int argc,wchar_t** argv){
94
+ if(argc!=8)fail("usage_root_relative_offset_length_hash_expectedrootdev_expectedrootino");
95
+ const std::wstring root=argv[1];
96
+ if(root.size()<4||root.size()>2048||root[1]!=L':'||(root[2]!=L'\\'&&root[2]!=L'/'))
97
+ fail("root_must_be_absolute_drive_path");
98
+ const auto names=split(argv[2]);
99
+ const auto offset=parseNumber(argv[3]),requested=parseNumber(argv[4]);
100
+ if(requested>4*1024*1024ULL||offset>9007199254740991ULL)fail("range_budget");
101
+ if(std::wcscmp(argv[5],L"0")!=0&&std::wcscmp(argv[5],L"1")!=0)fail("invalid_hash_mode");
102
+ const bool wantHash=argv[5][0]==L'1';
103
+ const auto expectedRootDev=parseNumber(argv[6]);
104
+ const auto expectedRootIno=parseNumber(argv[7]);
105
+ if(expectedRootDev>0xffffffffULL||expectedRootIno==0)fail("invalid_root_identity");
106
+ const HANDLE rootHandle=CreateFileW(root.c_str(),FILE_READ_ATTRIBUTES|FILE_LIST_DIRECTORY|SYNCHRONIZE,
107
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,nullptr,OPEN_EXISTING,
108
+ FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OPEN_REPARSE_POINT,nullptr);
109
+ if(rootHandle==INVALID_HANDLE_VALUE)fail("open_root");
110
+ if(!noReparse(rootHandle))fail("root_reparse_or_unverified");
111
+ FILE_ID_INFO rootId{};if(!GetFileInformationByHandleEx(rootHandle,FileIdInfo,&rootId,sizeof(rootId)))
112
+ fail("root_identity_unavailable");
113
+ unsigned long long openedRootIno=0;
114
+ std::memcpy(&openedRootIno,rootId.FileId.Identifier,sizeof(openedRootIno));
115
+ if((rootId.VolumeSerialNumber & 0xffffffffULL)!=expectedRootDev || openedRootIno!=expectedRootIno)
116
+ fail("root_identity_mismatch",6); // IMPORTANT: no leaf path has been opened
117
+ HMODULE ntdll=GetModuleHandleW(L"ntdll.dll");
118
+ auto nt=reinterpret_cast<NtCreateFilePtr>(GetProcAddress(ntdll,"NtCreateFile"));
119
+ if(!nt)fail("ntcreatefile_unavailable");
120
+ HANDLE parent=rootHandle;std::vector<HANDLE> chain;chain.reserve(names.size());
121
+ for(size_t i=0;i<names.size();++i){
122
+ const bool dir=i+1<names.size();
123
+ UNICODE_STRING name{};name.Buffer=const_cast<PWSTR>(names[i].c_str());
124
+ name.Length=static_cast<USHORT>(names[i].size()*sizeof(wchar_t));
125
+ name.MaximumLength=name.Length;
126
+ OBJECT_ATTRIBUTES oa{};oa.Length=sizeof(oa);oa.RootDirectory=parent;
127
+ oa.ObjectName=&name;oa.Attributes=OBJ_CASE_INSENSITIVE|kObjNoReparse;
128
+ IO_STATUS_BLOCK ios{};HANDLE next=nullptr;
129
+ const ULONG options=kFileSync|kFileNoReparse|(dir?kFileDir:kFileNotDir);
130
+ const ACCESS_MASK access=FILE_READ_ATTRIBUTES|SYNCHRONIZE|(dir?FILE_LIST_DIRECTORY:FILE_READ_DATA);
131
+ const NTSTATUS status=nt(&next,access,&oa,&ios,nullptr,FILE_ATTRIBUTE_NORMAL,
132
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,kFileOpen,options,nullptr,0);
133
+ if(status<0||!next)fail("nt_open_component_refused",3);
134
+ chain.push_back(next);
135
+ if(!noReparse(next))fail("component_reparse_or_unverified",4);
136
+ FILE_ID_INFO id{};if(!GetFileInformationByHandleEx(next,FileIdInfo,&id,sizeof(id)))
137
+ fail("component_identity_unavailable",5);
138
+ parent=next;
139
+ }
140
+ const HANDLE leaf=chain.back();
141
+ FILE_ID_INFO identity{};
142
+ FILE_BASIC_INFO initialBasic{},finalBasic{};
143
+ FILE_STANDARD_INFO initialStandard{},finalStandard{};
144
+ if(!GetFileInformationByHandleEx(leaf,FileIdInfo,&identity,sizeof(identity)) ||
145
+ !GetFileInformationByHandleEx(leaf,FileBasicInfo,&initialBasic,sizeof(initialBasic)) ||
146
+ !GetFileInformationByHandleEx(leaf,FileStandardInfo,&initialStandard,sizeof(initialStandard)))
147
+ fail("file_identity_unavailable");
148
+ const auto fileSize=initialStandard.EndOfFile.QuadPart;
149
+ if(fileSize<0||fileSize>9007199254740991LL)fail("file_size_out_of_range");
150
+ if(offset>static_cast<unsigned long long>(fileSize))fail("offset_exceeds_size");
151
+ const auto length=static_cast<size_t>(std::min(requested,static_cast<unsigned long long>(fileSize)-offset));
152
+ std::vector<unsigned char> data(length);
153
+ seek(leaf,offset);
154
+ size_t read=0;
155
+ while(read<length){
156
+ DWORD got=0;
157
+ if(!ReadFile(leaf,data.data()+read,static_cast<DWORD>(length-read),&got,nullptr))
158
+ fail("range_read_failed");
159
+ if(got==0)fail("unexpected_range_eof");
160
+ read+=got;
161
+ }
162
+ const auto digest=wantHash?hashAll(leaf):std::string();
163
+ if(!GetFileInformationByHandleEx(leaf,FileBasicInfo,&finalBasic,sizeof(finalBasic))||
164
+ !GetFileInformationByHandleEx(leaf,FileStandardInfo,&finalStandard,sizeof(finalStandard)))
165
+ fail("file_postidentity_unavailable");
166
+ if(initialStandard.EndOfFile.QuadPart!=finalStandard.EndOfFile.QuadPart||
167
+ initialBasic.LastWriteTime.QuadPart!=finalBasic.LastWriteTime.QuadPart||
168
+ initialBasic.ChangeTime.QuadPart!=finalBasic.ChangeTime.QuadPart)
169
+ fail("file_mutated_during_read");
170
+ unsigned long long nativeId=0;
171
+ std::memcpy(&nativeId,identity.FileId.Identifier,sizeof(nativeId));
172
+ const auto encoded=base64(data.data(),data.size());
173
+ std::printf("{\"schema\":\"deadbyte.machine-fs-read-worker.v1\",\"bytes_read\":%llu,\"data_base64\":\"%s\",\"file_sha256\":",
174
+ static_cast<unsigned long long>(read),encoded.c_str());
175
+ if(wantHash)std::printf("\"%s\"",digest.c_str());else std::printf("null");
176
+ std::printf(",\"file_size\":%llu,\"file_dev\":\"%llu\",\"file_ino\":\"%llu\"}",
177
+ static_cast<unsigned long long>(fileSize),
178
+ static_cast<unsigned long long>(identity.VolumeSerialNumber & 0xffffffffULL),nativeId);
179
+ for(auto it=chain.rbegin();it!=chain.rend();++it)CloseHandle(*it);
180
+ CloseHandle(rootHandle);return 0;
181
+ }
@@ -0,0 +1,97 @@
1
+ #define WIN32_LEAN_AND_MEAN
2
+ #include <windows.h>
3
+ #include <winternl.h>
4
+ #include <cstdio>
5
+ #include <cstdlib>
6
+ #include <cstring>
7
+ #include <cwchar>
8
+ #include <string>
9
+ #include <vector>
10
+ #include <algorithm>
11
+
12
+ // No content read. This proof worker demonstrates handle-anchored, no-reparse
13
+ // traversal. It is NOT wired into machine-fs read or exposed as a public tool.
14
+ using NtCreateFilePtr=NTSTATUS (NTAPI *)(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,
15
+ PIO_STATUS_BLOCK,PLARGE_INTEGER,ULONG,ULONG,ULONG,ULONG,PVOID,ULONG);
16
+ static constexpr ULONG kFileOpen=1;
17
+ static constexpr ULONG kFileDir=0x00000001;
18
+ static constexpr ULONG kFileNotDir=0x00000040;
19
+ static constexpr ULONG kFileSync=0x00000020;
20
+ static constexpr ULONG kFileNoReparse=0x00200000;
21
+ static constexpr ULONG kObjNoReparse=0x00001000;
22
+
23
+ static void fail(const char* m,int exitCode=2){
24
+ std::fprintf(stderr,"R197_NATIVE_REFUSE=%s\n",m);
25
+ std::exit(exitCode);
26
+ }
27
+ static bool noReparse(HANDLE h){
28
+ FILE_ATTRIBUTE_TAG_INFO t{};
29
+ if(!GetFileInformationByHandleEx(h,FileAttributeTagInfo,&t,sizeof(t)))return false;
30
+ return (t.FileAttributes&FILE_ATTRIBUTE_REPARSE_POINT)==0;
31
+ }
32
+ static bool fileIdentity(HANDLE h,FILE_ID_INFO& out){
33
+ return GetFileInformationByHandleEx(h,FileIdInfo,&out,sizeof(out))!=0;
34
+ }
35
+ static std::vector<std::wstring> split(const std::wstring& rel){
36
+ if(rel.empty()||rel.size()>1024||rel[0]==L'\\'||rel[0]==L'/'||
37
+ rel.find(L':')!=std::wstring::npos)fail("invalid_relative_path");
38
+ std::vector<std::wstring> segments;size_t start=0;
39
+ for(size_t i=0;i<=rel.size();++i){
40
+ if(i==rel.size()||rel[i]==L'/'||rel[i]==L'\\'){
41
+ auto s=rel.substr(start,i-start);
42
+ if(s.empty()||s==L"."||s==L".."||s.size()>255||
43
+ s.back()==L'.'||s.back()==L' '||s.find(L'\0')!=std::wstring::npos)fail("invalid_segment");
44
+ segments.push_back(std::move(s));start=i+1;
45
+ }
46
+ }
47
+ if(segments.empty()||segments.size()>32)fail("segment_budget");
48
+ return segments;
49
+ }
50
+ int wmain(int argc,wchar_t** argv){
51
+ if(argc!=3)fail("usage_root_and_relative");
52
+ const std::wstring root=argv[1];
53
+ if(root.size()<4||root.size()>2048||root[1]!=L':'||
54
+ (root[2]!=L'\\'&&root[2]!=L'/'))fail("root_must_be_absolute_drive_path");
55
+ const auto names=split(argv[2]);
56
+ const HANDLE rootHandle=CreateFileW(root.c_str(),FILE_READ_ATTRIBUTES|FILE_LIST_DIRECTORY|SYNCHRONIZE,
57
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,nullptr,OPEN_EXISTING,
58
+ FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OPEN_REPARSE_POINT,nullptr);
59
+ if(rootHandle==INVALID_HANDLE_VALUE)fail("open_root");
60
+ if(!noReparse(rootHandle))fail("root_reparse_or_unverified");
61
+ FILE_ID_INFO rootId{};if(!fileIdentity(rootHandle,rootId))fail("root_identity_unavailable");
62
+ HMODULE ntdll=GetModuleHandleW(L"ntdll.dll");
63
+ const auto nt=reinterpret_cast<NtCreateFilePtr>(GetProcAddress(ntdll,"NtCreateFile"));
64
+ if(!nt)fail("ntcreatefile_unavailable");
65
+ HANDLE parent=rootHandle;
66
+ std::vector<HANDLE> handles;handles.reserve(names.size());
67
+ for(size_t i=0;i<names.size();++i){
68
+ const bool directory=i+1<names.size();
69
+ UNICODE_STRING component{};
70
+ component.Buffer=const_cast<PWSTR>(names[i].c_str());
71
+ component.Length=static_cast<USHORT>(names[i].size()*sizeof(wchar_t));
72
+ component.MaximumLength=component.Length;
73
+ OBJECT_ATTRIBUTES oa{};
74
+ oa.Length=sizeof(oa);oa.RootDirectory=parent;oa.ObjectName=&component;
75
+ oa.Attributes=OBJ_CASE_INSENSITIVE|kObjNoReparse;
76
+ IO_STATUS_BLOCK ios{};
77
+ HANDLE next=nullptr;
78
+ const ULONG options=kFileSync|kFileNoReparse|(directory?kFileDir:kFileNotDir);
79
+ const ACCESS_MASK access=FILE_READ_ATTRIBUTES|SYNCHRONIZE|(directory?FILE_LIST_DIRECTORY:FILE_READ_DATA);
80
+ const NTSTATUS status=nt(&next,access,&oa,&ios,nullptr,FILE_ATTRIBUTE_NORMAL,
81
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,kFileOpen,options,nullptr,0);
82
+ if(status<0||next==nullptr)fail("nt_open_component_refused",3);
83
+ handles.push_back(next);
84
+ if(!noReparse(next))fail("component_reparse_or_unverified",4);
85
+ FILE_ID_INFO id{};if(!fileIdentity(next,id))fail("component_identity_unavailable",5);
86
+ parent=next;
87
+ }
88
+ const HANDLE leaf=handles.back();
89
+ LARGE_INTEGER size{};
90
+ if(!GetFileSizeEx(leaf,&size)||size.QuadPart<0)fail("file_size_unavailable");
91
+ std::printf("R197_NATIVE_HANDLE_RELATIVE_OPEN_PASS bytes=%llu components=%llu\n",
92
+ static_cast<unsigned long long>(size.QuadPart),
93
+ static_cast<unsigned long long>(handles.size()));
94
+ for(auto it=handles.rbegin();it!=handles.rend();++it)CloseHandle(*it);
95
+ CloseHandle(rootHandle);
96
+ return 0;
97
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deadbyte-mcp",
3
- "version": "0.15.74",
3
+ "version": "0.15.76",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Authenticated MCP agentic runtime with signed skills, persistent model backends, identity-bound remote devices, durable job supervision, immutable release slots, and separately revocable machine authority.",
@@ -9,6 +9,9 @@
9
9
  },
10
10
  "scripts": {
11
11
  "test": "node --test --test-concurrency=4 test/*.test.mjs",
12
+ "r195:focused:test": "node --test test/r195-canonical-owner-observation.test.mjs test/r193-owner-enrollment-entrypoint.test.mjs test/r193-owner-uac-broker.test.mjs test/r193-owner-uac-entrypoint.test.mjs test/r186-owner-enrollment.test.mjs test/r188-owner-uac.test.mjs",
13
+ "r206:focused:test": "node --test --test-concurrency=1 test/r205-candidate-selection.test.mjs test/r205-candidate-selection-cli.test.mjs test/r206-candidate-evidence.test.mjs test/r206-release-contract.test.mjs test/r195-canonical-owner-observation.test.mjs",
14
+ "r207:focused:test": "node --test --test-concurrency=1 test/r207-owner-enrollment-io.test.mjs test/r207-release-contract.test.mjs test/r193-owner-uac-broker.test.mjs test/r193-owner-uac-entrypoint.test.mjs test/r193-owner-enrollment-entrypoint.test.mjs test/r195-canonical-owner-observation.test.mjs",
12
15
  "manifest:write": "node scripts/release-manifest.mjs write",
13
16
  "manifest:verify": "node scripts/release-manifest.mjs verify",
14
17
  "r41:parent:verify": "node scripts/verify-r41-parent.mjs",
@@ -95,7 +98,7 @@
95
98
  "r67:shard:run": "node scripts/r67-regression-shard-run.mjs",
96
99
  "r67:shard:verify": "node scripts/r67-regression-reconcile.mjs",
97
100
  "r167:focused:test": "node --test --test-concurrency=1 test/r167-activation-path.test.mjs test/r167-release-contract.test.mjs test/r167-release-readiness.test.mjs test/r160-release-contract.test.mjs test/r158-epoch-bootstrap.test.mjs test/r65-activation-orchestration.test.mjs",
98
- "gate:windows": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r194.ps1 -Stage all",
101
+ "gate:windows": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r207.ps1 -Stage all",
99
102
  "r168:focused:test": "node test/r168-combined-targeted-runner.mjs",
100
103
  "r168:release:verify": "node scripts/npm-release-r48.mjs --verify-only",
101
104
  "r172:focused:test": "node --test --test-concurrency=1 test/r172-activation-recovery.test.mjs test/r172-release-contract.test.mjs test/r169-delegate-active.test.mjs test/r169-delegate-cli-integration.test.mjs test/r65-activation-lock-recovery.test.mjs test/r65-activation-orchestration.test.mjs",
@@ -0,0 +1,28 @@
1
+ #requires -Version 5.1
2
+ [CmdletBinding()]
3
+ param([Parameter(Mandatory=$true)][ValidatePattern('^[0-9a-f]{64}$')][string]$SourceSha256)
4
+ Set-StrictMode -Version Latest
5
+ $ErrorActionPreference='Stop'
6
+ $repo=Split-Path -Parent $PSScriptRoot
7
+ $src=Join-Path $repo 'native\deadbyte-desktop-uia-r199.cpp'
8
+ $actual=(Get-FileHash -LiteralPath $src -Algorithm SHA256).Hash.ToLowerInvariant()
9
+ if($actual -cne $SourceSha256){throw 'R197_NATIVE_SOURCE_HASH_DRIFT'}
10
+ $vswhere='C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe'
11
+ if(!(Test-Path -LiteralPath $vswhere)){throw 'R197_MSVC_UNAVAILABLE'}
12
+ $install=(& $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath | Select-Object -First 1)
13
+ if(!$install){throw 'R197_MSVC_TOOLCHAIN_MISSING'}
14
+ $dev=Join-Path $install 'Common7\Tools\VsDevCmd.bat'
15
+ $bin=Join-Path $repo 'bin'
16
+ $exe=Join-Path $bin 'deadbyte-desktop-uia-r199-fixed.exe'
17
+ $obj=Join-Path $bin 'deadbyte-desktop-uia-r199-fixed.obj'
18
+ if(Test-Path -LiteralPath $exe){throw 'R197_NATIVE_OUTPUT_EXISTS'}
19
+ if(Test-Path -LiteralPath $obj){throw 'R197_NATIVE_OBJECT_EXISTS'}
20
+ $common='/nologo /std:c++17 /permissive- /W4 /WX /O2 /MT /EHsc /guard:cf /diagnostics:caret /utf-8 /Brepro /DUNICODE /D_UNICODE /D_WIN32_WINNT=0x0A00'
21
+ $compile='cl {0} "{1}" /Fo:"{2}" /Fe:"{3}" user32.lib ole32.lib oleaut32.lib uiautomationcore.lib /link /Brepro /INCREMENTAL:NO' -f $common,$src,$obj,$exe
22
+ $cmd=Join-Path $env:SystemRoot 'System32\cmd.exe'
23
+ $line='call "{0}" -no_logo -arch=x64 -host_arch=x64 && {1}' -f $dev,$compile
24
+ & $cmd /d /s /c $line
25
+ if($LASTEXITCODE -ne 0){throw ('R197_NATIVE_COMPILATION_FAIL exit='+$LASTEXITCODE)}
26
+ if(!(Test-Path -LiteralPath $exe -PathType Leaf)){throw 'R197_NATIVE_OUTPUT_MISSING'}
27
+ $hash=(Get-FileHash -LiteralPath $exe -Algorithm SHA256).Hash.ToLowerInvariant()
28
+ Write-Output ('R197_NATIVE_BUILD_PASS exe_sha256='+$hash)
@@ -0,0 +1,28 @@
1
+ #requires -Version 5.1
2
+ [CmdletBinding()]
3
+ param([Parameter(Mandatory=$true)][ValidatePattern('^[0-9a-f]{64}$')][string]$SourceSha256)
4
+ Set-StrictMode -Version Latest
5
+ $ErrorActionPreference='Stop'
6
+ $repo=Split-Path -Parent $PSScriptRoot
7
+ $src=Join-Path $repo 'native\deadbyte-desktop-uia-r199.cpp'
8
+ $actual=(Get-FileHash -LiteralPath $src -Algorithm SHA256).Hash.ToLowerInvariant()
9
+ if($actual -cne $SourceSha256){throw 'R197_NATIVE_SOURCE_HASH_DRIFT'}
10
+ $vswhere='C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe'
11
+ if(!(Test-Path -LiteralPath $vswhere)){throw 'R197_MSVC_UNAVAILABLE'}
12
+ $install=(& $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath | Select-Object -First 1)
13
+ if(!$install){throw 'R197_MSVC_TOOLCHAIN_MISSING'}
14
+ $dev=Join-Path $install 'Common7\Tools\VsDevCmd.bat'
15
+ $bin=Join-Path $repo 'bin'
16
+ $exe=Join-Path $bin 'deadbyte-desktop-uia-r199.exe'
17
+ $obj=Join-Path $bin 'deadbyte-desktop-uia-r199.obj'
18
+ if(Test-Path -LiteralPath $exe){throw 'R197_NATIVE_OUTPUT_EXISTS'}
19
+ if(Test-Path -LiteralPath $obj){throw 'R197_NATIVE_OBJECT_EXISTS'}
20
+ $common='/nologo /std:c++17 /permissive- /W4 /WX /O2 /MT /EHsc /guard:cf /diagnostics:caret /utf-8 /Brepro /DUNICODE /D_UNICODE /D_WIN32_WINNT=0x0A00'
21
+ $compile='cl {0} "{1}" /Fo:"{2}" /Fe:"{3}" user32.lib ole32.lib oleaut32.lib uiautomationcore.lib /link /Brepro /INCREMENTAL:NO' -f $common,$src,$obj,$exe
22
+ $cmd=Join-Path $env:SystemRoot 'System32\cmd.exe'
23
+ $line='call "{0}" -no_logo -arch=x64 -host_arch=x64 && {1}' -f $dev,$compile
24
+ & $cmd /d /s /c $line
25
+ if($LASTEXITCODE -ne 0){throw ('R197_NATIVE_COMPILATION_FAIL exit='+$LASTEXITCODE)}
26
+ if(!(Test-Path -LiteralPath $exe -PathType Leaf)){throw 'R197_NATIVE_OUTPUT_MISSING'}
27
+ $hash=(Get-FileHash -LiteralPath $exe -Algorithm SHA256).Hash.ToLowerInvariant()
28
+ Write-Output ('R197_NATIVE_BUILD_PASS exe_sha256='+$hash)
@@ -0,0 +1,28 @@
1
+ #requires -Version 5.1
2
+ [CmdletBinding()]
3
+ param([Parameter(Mandatory=$true)][ValidatePattern('^[0-9a-f]{64}$')][string]$SourceSha256)
4
+ Set-StrictMode -Version Latest
5
+ $ErrorActionPreference='Stop'
6
+ $repo=Split-Path -Parent $PSScriptRoot
7
+ $src=Join-Path $repo 'native\deadbyte-fs-read-r197.cpp'
8
+ $actual=(Get-FileHash -LiteralPath $src -Algorithm SHA256).Hash.ToLowerInvariant()
9
+ if($actual -cne $SourceSha256){throw 'R197_NATIVE_SOURCE_HASH_DRIFT'}
10
+ $vswhere='C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe'
11
+ if(!(Test-Path -LiteralPath $vswhere)){throw 'R197_MSVC_UNAVAILABLE'}
12
+ $install=(& $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath | Select-Object -First 1)
13
+ if(!$install){throw 'R197_MSVC_TOOLCHAIN_MISSING'}
14
+ $dev=Join-Path $install 'Common7\Tools\VsDevCmd.bat'
15
+ $bin=Join-Path $repo 'bin'
16
+ $exe=Join-Path $bin 'deadbyte-fs-read-r197-fixed.exe'
17
+ $obj=Join-Path $bin 'deadbyte-fs-read-r197-fixed.obj'
18
+ if(Test-Path -LiteralPath $exe){throw 'R197_NATIVE_OUTPUT_EXISTS'}
19
+ if(Test-Path -LiteralPath $obj){throw 'R197_NATIVE_OBJECT_EXISTS'}
20
+ $common='/nologo /std:c++17 /permissive- /W4 /WX /O2 /MT /EHsc /guard:cf /diagnostics:caret /utf-8 /Brepro /DUNICODE /D_UNICODE /D_WIN32_WINNT=0x0A00'
21
+ $compile='cl {0} "{1}" /Fo:"{2}" /Fe:"{3}" /link /Brepro /INCREMENTAL:NO' -f $common,$src,$obj,$exe
22
+ $cmd=Join-Path $env:SystemRoot 'System32\cmd.exe'
23
+ $line='call "{0}" -no_logo -arch=x64 -host_arch=x64 && {1}' -f $dev,$compile
24
+ & $cmd /d /s /c $line
25
+ if($LASTEXITCODE -ne 0){throw ('R197_NATIVE_COMPILATION_FAIL exit='+$LASTEXITCODE)}
26
+ if(!(Test-Path -LiteralPath $exe -PathType Leaf)){throw 'R197_NATIVE_OUTPUT_MISSING'}
27
+ $hash=(Get-FileHash -LiteralPath $exe -Algorithm SHA256).Hash.ToLowerInvariant()
28
+ Write-Output ('R197_NATIVE_BUILD_PASS exe_sha256='+$hash)
@@ -0,0 +1,28 @@
1
+ #requires -Version 5.1
2
+ [CmdletBinding()]
3
+ param([Parameter(Mandatory=$true)][ValidatePattern('^[0-9a-f]{64}$')][string]$SourceSha256)
4
+ Set-StrictMode -Version Latest
5
+ $ErrorActionPreference='Stop'
6
+ $repo=Split-Path -Parent $PSScriptRoot
7
+ $src=Join-Path $repo 'native\deadbyte-fs-read-r197.cpp'
8
+ $actual=(Get-FileHash -LiteralPath $src -Algorithm SHA256).Hash.ToLowerInvariant()
9
+ if($actual -cne $SourceSha256){throw 'R197_NATIVE_SOURCE_HASH_DRIFT'}
10
+ $vswhere='C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe'
11
+ if(!(Test-Path -LiteralPath $vswhere)){throw 'R197_MSVC_UNAVAILABLE'}
12
+ $install=(& $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath | Select-Object -First 1)
13
+ if(!$install){throw 'R197_MSVC_TOOLCHAIN_MISSING'}
14
+ $dev=Join-Path $install 'Common7\Tools\VsDevCmd.bat'
15
+ $bin=Join-Path $repo 'bin'
16
+ $exe=Join-Path $bin 'deadbyte-fs-read-r197.exe'
17
+ $obj=Join-Path $bin 'deadbyte-fs-read-r197.obj'
18
+ if(Test-Path -LiteralPath $exe){throw 'R197_NATIVE_OUTPUT_EXISTS'}
19
+ if(Test-Path -LiteralPath $obj){throw 'R197_NATIVE_OBJECT_EXISTS'}
20
+ $common='/nologo /std:c++17 /permissive- /W4 /WX /O2 /MT /EHsc /guard:cf /diagnostics:caret /utf-8 /Brepro /DUNICODE /D_UNICODE /D_WIN32_WINNT=0x0A00'
21
+ $compile='cl {0} "{1}" /Fo:"{2}" /Fe:"{3}" /link /Brepro /INCREMENTAL:NO' -f $common,$src,$obj,$exe
22
+ $cmd=Join-Path $env:SystemRoot 'System32\cmd.exe'
23
+ $line='call "{0}" -no_logo -arch=x64 -host_arch=x64 && {1}' -f $dev,$compile
24
+ & $cmd /d /s /c $line
25
+ if($LASTEXITCODE -ne 0){throw ('R197_NATIVE_COMPILATION_FAIL exit='+$LASTEXITCODE)}
26
+ if(!(Test-Path -LiteralPath $exe -PathType Leaf)){throw 'R197_NATIVE_OUTPUT_MISSING'}
27
+ $hash=(Get-FileHash -LiteralPath $exe -Algorithm SHA256).Hash.ToLowerInvariant()
28
+ Write-Output ('R197_NATIVE_BUILD_PASS exe_sha256='+$hash)
@@ -0,0 +1,28 @@
1
+ #requires -Version 5.1
2
+ [CmdletBinding()]
3
+ param([Parameter(Mandatory=$true)][ValidatePattern('^[0-9a-f]{64}$')][string]$SourceSha256)
4
+ Set-StrictMode -Version Latest
5
+ $ErrorActionPreference='Stop'
6
+ $repo=Split-Path -Parent $PSScriptRoot
7
+ $src=Join-Path $repo 'native\deadbyte-fs-read-r198.cpp'
8
+ $actual=(Get-FileHash -LiteralPath $src -Algorithm SHA256).Hash.ToLowerInvariant()
9
+ if($actual -cne $SourceSha256){throw 'R197_NATIVE_SOURCE_HASH_DRIFT'}
10
+ $vswhere='C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe'
11
+ if(!(Test-Path -LiteralPath $vswhere)){throw 'R197_MSVC_UNAVAILABLE'}
12
+ $install=(& $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath | Select-Object -First 1)
13
+ if(!$install){throw 'R197_MSVC_TOOLCHAIN_MISSING'}
14
+ $dev=Join-Path $install 'Common7\Tools\VsDevCmd.bat'
15
+ $bin=Join-Path $repo 'bin'
16
+ $exe=Join-Path $bin 'deadbyte-fs-read-r198.exe'
17
+ $obj=Join-Path $bin 'deadbyte-fs-read-r198.obj'
18
+ if(Test-Path -LiteralPath $exe){throw 'R197_NATIVE_OUTPUT_EXISTS'}
19
+ if(Test-Path -LiteralPath $obj){throw 'R197_NATIVE_OBJECT_EXISTS'}
20
+ $common='/nologo /std:c++17 /permissive- /W4 /WX /O2 /MT /EHsc /guard:cf /diagnostics:caret /utf-8 /Brepro /DUNICODE /D_UNICODE /D_WIN32_WINNT=0x0A00'
21
+ $compile='cl {0} "{1}" /Fo:"{2}" /Fe:"{3}" /link /Brepro /INCREMENTAL:NO' -f $common,$src,$obj,$exe
22
+ $cmd=Join-Path $env:SystemRoot 'System32\cmd.exe'
23
+ $line='call "{0}" -no_logo -arch=x64 -host_arch=x64 && {1}' -f $dev,$compile
24
+ & $cmd /d /s /c $line
25
+ if($LASTEXITCODE -ne 0){throw ('R197_NATIVE_COMPILATION_FAIL exit='+$LASTEXITCODE)}
26
+ if(!(Test-Path -LiteralPath $exe -PathType Leaf)){throw 'R197_NATIVE_OUTPUT_MISSING'}
27
+ $hash=(Get-FileHash -LiteralPath $exe -Algorithm SHA256).Hash.ToLowerInvariant()
28
+ Write-Output ('R197_NATIVE_BUILD_PASS exe_sha256='+$hash)