├── .gitignore
├── README.md
├── UNLICENSE
├── build.ps1
├── uwpspy.cpp
└── vcvarsall17.ps1
/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
2 | *.obj
3 | *.dll
4 | *.swp
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | dll that hooks various uwp interfaces for debugging and reverse engineering
2 |
3 | # compiling
4 | install visual c++ build tools 2017 and the windows 10 sdk
5 |
6 | open powershell and navigate to uwpspy
7 |
8 | ```ps1
9 | .\vcvarsall17.ps1
10 | .\build.ps1
11 | ```
12 |
13 | # usage
14 | use an injector that can fix permissions for uwp apps like
15 | https://github.com/Francesco149/uwpinject
16 |
17 | a console should pop up and start logging on injection
18 |
--------------------------------------------------------------------------------
/UNLICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/build.ps1:
--------------------------------------------------------------------------------
1 | $invocation = (Get-Variable MyInvocation).Value
2 | $dir = Split-Path $invocation.MyCommand.Path
3 | Write-Output "working dir: $dir"
4 |
5 | function Write-Header {
6 | param ([string]$Message)
7 | $oldcolor = $host.UI.RawUI.ForegroundColor
8 | $host.UI.RawUI.ForegroundColor = "Green"
9 | Write-Output ":: $Message"
10 | $host.UI.RawUI.ForegroundColor = $oldcolor
11 | }
12 |
13 | Push-Location $dir
14 | $res = $null
15 | try {
16 | Write-Header "linting"
17 | $hasAnalyzer = Get-Command "Invoke-ScriptAnalyzer" `
18 | -ErrorAction SilentlyContinue
19 | if (-not $hasAnalyzer) {
20 | Write-Warning "you're missing PSScriptAnalyzer, skipping lint step"
21 | return
22 | }
23 | $results = Invoke-ScriptAnalyzer -Path . -Recurse
24 | foreach ($result in $results) {
25 | Write-Output ($result | Format-Table | Out-String)
26 | }
27 | if ($results.Count -ne 0) {
28 | Throw "did not pass ps1 linting"
29 | }
30 | Get-ChildItem -file -Recurse . |
31 | Where-Object { $_.Name -match ".*\.cpp" } |
32 | ForEach-Object -Process {
33 | $target = (Get-Item $_).Basename
34 | Write-Header "cleaning $target"
35 | Remove-Item "$target.obj", "$target.dll", "$target.exp", `
36 | "$target.lib", "$target.winmd" -ErrorAction SilentlyContinue
37 | Write-Header "compiling $_"
38 | cl /nologo /EHsc /Gm- /GR- /W4 /LD `
39 | /D_CRT_SECURE_NO_WARNINGS=1 $_
40 | if (-not $?) {
41 | Throw "cl failed: $LastExitCode"
42 | }
43 | }
44 | } catch {
45 | $res = $_
46 | }
47 | Pop-Location
48 | if ($null -ne $res) {
49 | Throw $res
50 | }
51 |
--------------------------------------------------------------------------------
/uwpspy.cpp:
--------------------------------------------------------------------------------
1 | // stubs for some uwp api's and interfaces
2 | // useful for debugging and reverse engineering
3 | // also a nice base to copypaste for hooking
4 |
5 | #define WIN32_LEAN_AND_MEAN
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #pragma comment (lib, "ole32.lib")
14 |
15 | namespace abi {
16 | using namespace ABI::Windows::UI::Core;
17 | using namespace ABI::Windows::ApplicationModel;
18 | using namespace ABI::Windows::ApplicationModel::Core;
19 | using namespace ABI::Windows::Foundation;
20 | using namespace ABI::Windows::Foundation::Collections;
21 | using namespace ABI::Windows::Foundation::Diagnostics;
22 | }
23 |
24 | #include
25 | #pragma intrinsic(_ReturnAddress)
26 |
27 | #include
28 | #include
29 | #include
30 |
31 | #define dbg \
32 | wprintf(L"[%hs:%d] %hs: ", __FILE__, __LINE__, __FUNCTION__), \
33 | wprintln
34 |
35 | int wprintln(WCHAR* fmt, ...) {
36 | int res = 0;
37 | va_list va;
38 | va_start(va, fmt);
39 | res += vwprintf(fmt, va);
40 | va_end(va);
41 | res += wprintf(L"\n");
42 | return res;
43 | }
44 |
45 | // ------------------------------------------------------------------------
46 |
47 | void log_init() {
48 | COORD bufsize;
49 | int success = (
50 | AttachConsole(ATTACH_PARENT_PROCESS) ||
51 | AttachConsole(GetCurrentProcessId()) ||
52 | AllocConsole()
53 | );
54 | if (success) {
55 | freopen("CONOUT$", "w", stdout);
56 | setvbuf(stdout, 0, _IONBF, 0);
57 | dbg(L"initialized console");
58 | } else {
59 | dbg(L"running in console mode");
60 | }
61 | bufsize.X = 80;
62 | bufsize.Y = 999;
63 | SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), bufsize);
64 | }
65 |
66 | typedef struct {
67 | void* addr;
68 | size_t n;
69 | DWORD fl;
70 | } spy_protection_t;
71 |
72 | int spy_protpush(spy_protection_t* prot, void* addr, size_t n) {
73 | DWORD oldprot;
74 | DWORD* poldprot;
75 | if (prot) {
76 | prot->addr = addr;
77 | prot->n = n;
78 | poldprot = &prot->fl;
79 | } else {
80 | poldprot = &oldprot;
81 | }
82 | if (!VirtualProtect(addr, n, PAGE_EXECUTE_READWRITE, poldprot)) {
83 | dbg(L"VirtualProtect %p failed: %08X", addr, GetLastError());
84 | return 0;
85 | }
86 | return 1;
87 | }
88 |
89 | int spy_protpop(spy_protection_t* prot) {
90 | DWORD dummy;
91 | if (!VirtualProtect(prot->addr, prot->n, prot->fl, &dummy)) {
92 | dbg(L"VirtualProtect failed: %08X", GetLastError());
93 | return 0;
94 | }
95 | return 1;
96 | }
97 |
98 | int spy_rva(void* base, DWORD* rva, void* hook) {
99 | spy_protection_t p;
100 | if (spy_protpush(&p, rva, sizeof(*rva))) {
101 | *rva = (DWORD)((char*)hook - (char*)base);
102 | return spy_protpop(&p);
103 | }
104 | return 0;
105 | }
106 |
107 | #if defined(_M_X64) && _M_X64 == 100
108 | #define JMPABS_SIZE 12
109 | #define JMPREL_SIZE 5
110 |
111 | void jmpabs(void* p, void* dst) {
112 | unsigned char* code = (unsigned char*)p;
113 | code = (unsigned char*)p;
114 | code[0] = 0x4E; /* mov rax,imm64 */
115 | code[1] = 0xB8;
116 | *(UINT64*)&code[2] = (UINT64)dst;
117 | code[10] = 0xFF; /* jmp rax */
118 | code[11] = 0xE0;
119 | }
120 |
121 | void jmprel(void* p, void* dst) {
122 | unsigned char* code = (unsigned char*)p;
123 | code = (unsigned char*)p;
124 | code[0] = 0xE9;
125 | *(INT32*)&code[1] = (INT32)((char*)dst - (char*)p - 5);
126 | }
127 |
128 | void* rel_alloc(void* base, size_t n) {
129 | ULONG_PTR scan_addr;
130 | SYSTEM_INFO si;
131 | ULONG_PTR min_addr;
132 | ULONG_PTR max_addr;
133 | /* scan for unused memory blocks in rel32 range */
134 | GetSystemInfo(&si);
135 | min_addr = max((ULONG_PTR)si.lpMinimumApplicationAddress,
136 | (ULONG_PTR)base - 0x40000000);
137 | max_addr = min((ULONG_PTR)si.lpMaximumApplicationAddress,
138 | (ULONG_PTR)base + 0x40000000);
139 | scan_addr = min_addr;
140 | scan_addr -= scan_addr % si.dwAllocationGranularity;
141 | while (scan_addr < max_addr) {
142 | MEMORY_BASIC_INFORMATION mbi;
143 | if (!VirtualQuery((void*)scan_addr, &mbi, sizeof(mbi))) {
144 | dbg(L"VirtualQuery failed: %08X", GetLastError());
145 | break;
146 | }
147 | if (mbi.State == MEM_FREE) {
148 | void* p = VirtualAlloc((void*)scan_addr, n,
149 | MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
150 | if (p) {
151 | return p;
152 | } else {
153 | dbg(L"VirtualAlloc failed: %08X", GetLastError());
154 | }
155 | }
156 | scan_addr = (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize;
157 | scan_addr += si.dwAllocationGranularity - 1;
158 | scan_addr -= scan_addr % si.dwAllocationGranularity;
159 | }
160 | return 0;
161 | }
162 | #else
163 | #error "arch not supported"
164 | #endif
165 |
166 | /*
167 | * using a short jump makes it easier to hook because it overwrites a lot
168 | * less code, which means I almost never have to hand-fix the trampoline
169 | *
170 | * target:
171 | * jmp rel -> relay
172 | * ...
173 | * target_ret:
174 | * ...
175 | *
176 | * relay:
177 | * mov rax,hook
178 | * jmp rax
179 | *
180 | * trampoline:
181 | * (orig code)
182 | * mov rax,target_ret
183 | * jmp rax
184 | */
185 |
186 | int spy_hook(void* func, void* hook, size_t nops, void** ptrampoline) {
187 | spy_protection_t p;
188 | char* relay = 0;
189 | size_t hook_size = JMPREL_SIZE + nops;
190 | if (!spy_protpush(&p, func, hook_size)) {
191 | return 0;
192 | }
193 | relay = (char*)rel_alloc(func, JMPABS_SIZE);
194 | if (!relay) {
195 | dbg(L"couldn't find free memory in rel range for %p", func);
196 | return 0;
197 | }
198 | if (!ptrampoline || !*ptrampoline) {
199 | size_t trampoline_size = hook_size + JMPABS_SIZE;
200 | char* trampoline = (char*)malloc(trampoline_size);
201 | if (!spy_protpush(0, trampoline, trampoline_size)) {
202 | return 0;
203 | }
204 | memcpy(trampoline, func, hook_size);
205 | jmpabs(&trampoline[hook_size], (char*)func + hook_size);
206 | if (ptrampoline) {
207 | *ptrampoline = trampoline;
208 | }
209 | }
210 | jmpabs(relay, hook);
211 | jmprel(func, relay);
212 | memset((char*)func + JMPREL_SIZE, 0x90, nops);
213 | return spy_protpop(&p);
214 | }
215 |
216 | typedef struct {
217 | char* name;
218 | void* hook;
219 | void** trampoline;
220 | int nops;
221 | } spy_export_t;
222 |
223 | int spy_exports(char* module_name, int n_hooks, spy_export_t* hooks) {
224 | char* module;
225 | IMAGE_NT_HEADERS* nt;
226 | IMAGE_DATA_DIRECTORY* dir;
227 | IMAGE_EXPORT_DIRECTORY* exports;
228 | DWORD i;
229 | DWORD* name_off;
230 | DWORD* function_off;
231 | WORD* ordinals;
232 |
233 | module = (char*)GetModuleHandleA(module_name);
234 | if (!module) {
235 | dbg(L"%hs not found", module_name);
236 | return 0;
237 | }
238 |
239 | nt = (IMAGE_NT_HEADERS*)(module + PIMAGE_DOS_HEADER(module)->e_lfanew);
240 | dir = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
241 | exports = (IMAGE_EXPORT_DIRECTORY*)(module + dir->VirtualAddress);
242 | name_off = (DWORD*)(module + exports->AddressOfNames);
243 | function_off = (DWORD*)(module + exports->AddressOfFunctions);
244 | ordinals = (WORD*)(module + exports->AddressOfNameOrdinals);
245 |
246 | dbg(L":: %hs", module_name);
247 |
248 | for (i = 0; i < exports->NumberOfNames; ++i) {
249 | char* name = module + name_off[i];
250 | int ordinal = (int)ordinals[i];
251 | unsigned char* func = (unsigned char*)module + function_off[ordinal];
252 | int j;
253 | for (j = 0; j < n_hooks; ++j) {
254 | spy_export_t* hook = &hooks[j];
255 | if (!_stricmp(hook->name, name)) {
256 | LONG_PTR distance = (char*)hook->hook - module;
257 | if (!hook->hook) {
258 | if (hook->trampoline) {
259 | *hook->trampoline = func;
260 | }
261 | break;
262 | }
263 | dbg(L"%p -> %hs @%d", func, name, ordinal);
264 | if (distance & ~(LONG_PTR)0xFFFFFFFF) {
265 | spy_hook(func, hook->hook, hook->nops, hook->trampoline);
266 | } else {
267 | dbg(L"function is nearby, using simple iat hook");
268 | spy_rva(module, &function_off[ordinal], hook->hook);
269 | if (hook->trampoline) {
270 | *hook->trampoline = func;
271 | }
272 | }
273 | break;
274 | }
275 | }
276 | }
277 |
278 | return 1;
279 | }
280 |
281 | // ------------------------------------------------------------------------
282 |
283 | PCWSTR (STDMETHODCALLTYPE* _WindowsGetStringRawBuffer)
284 | (HSTRING s, UINT32* len);
285 |
286 | // ------------------------------------------------------------------------
287 |
288 | #define dumpstr(x) dbg(L"" #x L"=%s", _WindowsGetStringRawBuffer(x, 0))
289 | #define dumpptr(fmt, x) dbg(L"" #x L"=%p -> " fmt, (x), (x) ? *(x) : 0)
290 | #define dumpiid(x) { \
291 | LPOLESTR iidstr; \
292 | if (StringFromIID(x, &iidstr) == S_OK) { \
293 | dbg(L"" #x L"=%s", iidstr); \
294 | CoTaskMemFree(iidstr); \
295 | } \
296 | }
297 | #define dump(fmt, x) dbg(L"" #x L"=" fmt, x)
298 |
299 | // ------------------------------------------------------------------------
300 |
301 | struct __declspec(uuid("00000035-0000-0000-C000-000000000046"))
302 | _IActivationFactory : public IActivationFactory {
303 | IActivationFactory* orig;
304 |
305 | explicit _IActivationFactory(IActivationFactory* orig)
306 | : orig(orig)
307 | {
308 | dump("%p", orig);
309 | }
310 |
311 | // IUnknown
312 |
313 | virtual HRESULT STDMETHODCALLTYPE
314 | QueryInterface(REFIID riid, void** obj) override
315 | {
316 | dbg(L"called from %p", _ReturnAddress());
317 | dumpiid(riid);
318 | HRESULT hr = orig->QueryInterface(riid, obj);
319 | dump("%08X", hr);
320 | if (SUCCEEDED(hr)) {
321 | dumpptr(L"%p", obj);
322 | }
323 | return hr;
324 | }
325 |
326 | virtual ULONG STDMETHODCALLTYPE AddRef() override {
327 | dbg(L"called from %p", _ReturnAddress());
328 | ULONG refcount = orig->AddRef();
329 | dump(L"%u", refcount);
330 | return refcount;
331 | }
332 |
333 | virtual ULONG STDMETHODCALLTYPE Release() override {
334 | dbg(L"called from %p", _ReturnAddress());
335 | ULONG refcount = orig->Release();
336 | dump(L"%u", refcount);
337 | if (!refcount) {
338 | delete this;
339 | }
340 | return refcount;
341 | }
342 |
343 | // IInspectable
344 |
345 | virtual HRESULT STDMETHODCALLTYPE
346 | GetIids(ULONG* n_iids, IID** iids) override
347 | {
348 | dbg(L"called from %p", _ReturnAddress());
349 | HRESULT hr = orig->GetIids(n_iids, iids);
350 | dump("%08X", hr);
351 | if (SUCCEEDED(hr)) {
352 | for (ULONG i = 0; i < *n_iids; ++i) {
353 | dumpiid((*iids)[i]);
354 | }
355 | }
356 | return hr;
357 | }
358 |
359 | virtual HRESULT STDMETHODCALLTYPE
360 | GetRuntimeClassName(HSTRING* name) override
361 | {
362 | dbg(L"called from %p", _ReturnAddress());
363 | HRESULT hr = orig->GetRuntimeClassName(name);
364 | dump("%08X", hr);
365 | if (SUCCEEDED(hr)) {
366 | dumpstr(*name);
367 | }
368 | return hr;
369 | }
370 |
371 | virtual HRESULT STDMETHODCALLTYPE GetTrustLevel(TrustLevel* l) override {
372 | dbg(L"called from %p", _ReturnAddress());
373 | HRESULT hr = orig->GetTrustLevel(l);
374 | dump("%08X", hr);
375 | if (SUCCEEDED(hr)) {
376 | char* level = "Unknown";
377 | switch (*l) {
378 | #define c(x) case x: level = #x; break
379 | c(BaseTrust);
380 | c(PartialTrust);
381 | c(FullTrust);
382 | #undef c
383 | }
384 | dump(L"%hs", level);
385 | }
386 | return hr;
387 | }
388 |
389 | // IActivationFactory
390 |
391 | virtual HRESULT STDMETHODCALLTYPE
392 | ActivateInstance(IInspectable** instance) override
393 | {
394 | dbg(L"called from %p", _ReturnAddress());
395 | HRESULT hr = orig->ActivateInstance(instance);
396 | dump("%08X", hr);
397 | if (SUCCEEDED(hr)) {
398 | dumpptr("%p", instance);
399 | }
400 | return hr;
401 | }
402 | };
403 |
404 | // ------------------------------------------------------------------------
405 |
406 | struct __declspec(uuid("CF86461D-261E-4B72-9ACD-44ED2ACE6A29"))
407 | _ICoreApplicationExit : public abi::ICoreApplicationExit {
408 | abi::ICoreApplicationExit* orig;
409 |
410 | explicit _ICoreApplicationExit(abi::ICoreApplicationExit* orig)
411 | : orig(orig)
412 | {
413 | dump("%p", orig);
414 | }
415 |
416 | // IUnknown
417 |
418 | virtual HRESULT STDMETHODCALLTYPE
419 | QueryInterface(REFIID riid, void** obj) override
420 | {
421 | dbg(L"called from %p", _ReturnAddress());
422 | dumpiid(riid);
423 | HRESULT hr = orig->QueryInterface(riid, obj);
424 | dump("%08X", hr);
425 | if (SUCCEEDED(hr)) {
426 | dumpptr(L"%p", obj);
427 | }
428 | return hr;
429 | }
430 |
431 | virtual ULONG STDMETHODCALLTYPE AddRef() override {
432 | dbg(L"called from %p", _ReturnAddress());
433 | ULONG refcount = orig->AddRef();
434 | dump(L"%u", refcount);
435 | return refcount;
436 | }
437 |
438 | virtual ULONG STDMETHODCALLTYPE Release() override {
439 | dbg(L"called from %p", _ReturnAddress());
440 | ULONG refcount = orig->Release();
441 | dump(L"%u", refcount);
442 | if (!refcount) {
443 | delete this;
444 | }
445 | return refcount;
446 | }
447 |
448 | // IInspectable
449 |
450 | virtual HRESULT STDMETHODCALLTYPE
451 | GetIids(ULONG* n_iids, IID** iids) override
452 | {
453 | dbg(L"called from %p", _ReturnAddress());
454 | HRESULT hr = orig->GetIids(n_iids, iids);
455 | dump("%08X", hr);
456 | if (SUCCEEDED(hr)) {
457 | for (ULONG i = 0; i < *n_iids; ++i) {
458 | dumpiid((*iids)[i]);
459 | }
460 | }
461 | return hr;
462 | }
463 |
464 | virtual HRESULT STDMETHODCALLTYPE
465 | GetRuntimeClassName(HSTRING* name) override
466 | {
467 | dbg(L"called from %p", _ReturnAddress());
468 | HRESULT hr = orig->GetRuntimeClassName(name);
469 | dump("%08X", hr);
470 | if (SUCCEEDED(hr)) {
471 | dumpstr(*name);
472 | }
473 | return hr;
474 | }
475 |
476 | virtual HRESULT STDMETHODCALLTYPE GetTrustLevel(TrustLevel* l) override {
477 | dbg(L"called from %p", _ReturnAddress());
478 | HRESULT hr = orig->GetTrustLevel(l);
479 | dump("%08X", hr);
480 | if (SUCCEEDED(hr)) {
481 | char* level = "Unknown";
482 | switch (*l) {
483 | #define c(x) case x: level = #x; break
484 | c(BaseTrust);
485 | c(PartialTrust);
486 | c(FullTrust);
487 | #undef c
488 | }
489 | dump(L"%hs", level);
490 | }
491 | return hr;
492 | }
493 |
494 | // ICoreApplicationExit
495 |
496 | virtual HRESULT STDMETHODCALLTYPE Exit() override {
497 | dbg(L"called from %p", _ReturnAddress());
498 | HRESULT hr = orig->Exit();
499 | dump("%08X", hr);
500 | return hr;
501 | }
502 |
503 | virtual HRESULT STDMETHODCALLTYPE add_Exiting(
504 | abi::IEventHandler* handler,
505 | EventRegistrationToken* token) override
506 | {
507 | dbg(L"called from %p", _ReturnAddress());
508 | HRESULT hr = orig->add_Exiting(handler, token);
509 | dump("%08X", hr);
510 | return hr;
511 | }
512 |
513 | virtual HRESULT STDMETHODCALLTYPE remove_Exiting(
514 | EventRegistrationToken token) override
515 | {
516 | dbg(L"called from %p", _ReturnAddress());
517 | HRESULT hr = orig->remove_Exiting(token);
518 | dump("%08X", hr);
519 | return hr;
520 | }
521 | };
522 |
523 | // ------------------------------------------------------------------------
524 |
525 |
526 | struct __declspec(uuid("0AACF7A4-5E1D-49DF-8034-FB6A68BC5ED1"))
527 | _ICoreApplication : public abi::ICoreApplication
528 | {
529 | abi::ICoreApplication* orig;
530 |
531 | explicit _ICoreApplication(abi::ICoreApplication* orig)
532 | : orig(orig)
533 | {
534 | dump("%p", orig);
535 | }
536 |
537 | // IUnknown
538 |
539 | virtual HRESULT STDMETHODCALLTYPE
540 | QueryInterface(REFIID riid, void** obj) override
541 | {
542 | void* res;
543 | dbg(L"called from %p", _ReturnAddress());
544 | dumpiid(riid);
545 | HRESULT hr = orig->QueryInterface(riid, &res);
546 | dump("%08X", hr);
547 | if (FAILED(hr)) {
548 | *obj = res;
549 | } else if (riid == __uuidof(abi::ICoreApplicationExit)) {
550 | *obj = new _ICoreApplicationExit((abi::ICoreApplicationExit*)res);
551 | } else {
552 | *obj = res;
553 | }
554 | if (SUCCEEDED(hr)) {
555 | dumpptr(L"%p", obj);
556 | }
557 | return hr;
558 | }
559 |
560 | virtual ULONG STDMETHODCALLTYPE AddRef() override {
561 | dbg(L"called from %p", _ReturnAddress());
562 | ULONG refcount = orig->AddRef();
563 | dump(L"%u", refcount);
564 | return refcount;
565 | }
566 |
567 | virtual ULONG STDMETHODCALLTYPE Release() override {
568 | dbg(L"called from %p", _ReturnAddress());
569 | ULONG refcount = orig->Release();
570 | dump(L"%u", refcount);
571 | if (!refcount) {
572 | delete this;
573 | }
574 | return refcount;
575 | }
576 |
577 | // IInspectable
578 |
579 | virtual HRESULT STDMETHODCALLTYPE
580 | GetIids(ULONG* n_iids, IID** iids) override
581 | {
582 | dbg(L"called from %p", _ReturnAddress());
583 | HRESULT hr = orig->GetIids(n_iids, iids);
584 | dump("%08X", hr);
585 | if (SUCCEEDED(hr)) {
586 | for (ULONG i = 0; i < *n_iids; ++i) {
587 | dumpiid((*iids)[i]);
588 | }
589 | }
590 | return hr;
591 | }
592 |
593 | virtual HRESULT STDMETHODCALLTYPE
594 | GetRuntimeClassName(HSTRING* name) override
595 | {
596 | dbg(L"called from %p", _ReturnAddress());
597 | HRESULT hr = orig->GetRuntimeClassName(name);
598 | dump("%08X", hr);
599 | if (SUCCEEDED(hr)) {
600 | dumpstr(*name);
601 | }
602 | return hr;
603 | }
604 |
605 | virtual HRESULT STDMETHODCALLTYPE GetTrustLevel(TrustLevel* l) override {
606 | dbg(L"called from %p", _ReturnAddress());
607 | HRESULT hr = orig->GetTrustLevel(l);
608 | dump("%08X", hr);
609 | if (SUCCEEDED(hr)) {
610 | char* level = "Unknown";
611 | switch (*l) {
612 | #define c(x) case x: level = #x; break
613 | c(BaseTrust);
614 | c(PartialTrust);
615 | c(FullTrust);
616 | #undef c
617 | }
618 | dump(L"%hs", level);
619 | }
620 | return hr;
621 | }
622 |
623 | // ICoreApplication
624 |
625 | virtual HRESULT STDMETHODCALLTYPE get_Id(HSTRING* value) override {
626 | dbg(L"called from %p", _ReturnAddress());
627 | HRESULT hr = orig->get_Id(value);
628 | dump("%08X", hr);
629 | if (SUCCEEDED(hr)) {
630 | dumpstr(*value);
631 | }
632 | return hr;
633 | }
634 |
635 | virtual HRESULT STDMETHODCALLTYPE add_Suspending(
636 | abi::IEventHandler* h,
637 | EventRegistrationToken* token) override
638 | {
639 | dbg(L"called from %p", _ReturnAddress());
640 | HRESULT hr = orig->add_Suspending(h, token);
641 | dump("%08X", hr);
642 | return hr;
643 | }
644 |
645 | virtual HRESULT STDMETHODCALLTYPE remove_Suspending(
646 | EventRegistrationToken token) override
647 | {
648 | dbg(L"called from %p", _ReturnAddress());
649 | HRESULT hr = orig->remove_Suspending(token);
650 | dump("%08X", hr);
651 | return hr;
652 | }
653 |
654 | virtual HRESULT STDMETHODCALLTYPE add_Resuming(
655 | abi::IEventHandler* handler,
656 | EventRegistrationToken* token) override
657 | {
658 | dbg(L"called from %p", _ReturnAddress());
659 | HRESULT hr = orig->add_Resuming(handler, token);
660 | dump("%08X", hr);
661 | return hr;
662 | }
663 |
664 | virtual HRESULT STDMETHODCALLTYPE remove_Resuming(
665 | EventRegistrationToken token) override
666 | {
667 | dbg(L"called from %p", _ReturnAddress());
668 | HRESULT hr = orig->remove_Resuming(token);
669 | dump("%08X", hr);
670 | return hr;
671 | }
672 |
673 | virtual HRESULT STDMETHODCALLTYPE get_Properties(
674 | abi::IPropertySet** value) override
675 | {
676 | dbg(L"called from %p", _ReturnAddress());
677 | HRESULT hr = orig->get_Properties(value);
678 | dump("%08X", hr);
679 | return hr;
680 | }
681 |
682 | virtual HRESULT STDMETHODCALLTYPE GetCurrentView(
683 | abi::ICoreApplicationView** value) override
684 | {
685 | dbg(L"called from %p", _ReturnAddress());
686 | HRESULT hr = orig->GetCurrentView(value);
687 | dump("%08X", hr);
688 | return hr;
689 | }
690 |
691 | virtual HRESULT STDMETHODCALLTYPE Run(
692 | abi::IFrameworkViewSource* s) override
693 | {
694 | dbg(L"called from %p", _ReturnAddress());
695 | HRESULT hr = orig->Run(s);
696 | dump("%08X", hr);
697 | return hr;
698 | }
699 |
700 | virtual HRESULT STDMETHODCALLTYPE RunWithActivationFactories(
701 | abi::IGetActivationFactory* callback) override
702 | {
703 | dbg(L"called from %p", _ReturnAddress());
704 | HRESULT hr = orig->RunWithActivationFactories(callback);
705 | dump("%08X", hr);
706 | return hr;
707 | }
708 | };
709 |
710 | // ------------------------------------------------------------------------
711 |
712 | struct __declspec(uuid("8A43ED9F-F4E6-4421-ACF9-1DAB2986820C"))
713 | _IPropertySet : public abi::IPropertySet {
714 | IPropertySet* orig;
715 |
716 | explicit _IPropertySet(abi::IPropertySet* orig)
717 | : orig(orig)
718 | {
719 | dump("%p", orig);
720 | }
721 |
722 | // IUnknown
723 |
724 | virtual HRESULT STDMETHODCALLTYPE
725 | QueryInterface(REFIID riid, void** obj) override
726 | {
727 | dbg(L"called from %p", _ReturnAddress());
728 | dumpiid(riid);
729 | HRESULT hr = orig->QueryInterface(riid, obj);
730 | dump("%08X", hr);
731 | if (SUCCEEDED(hr)) {
732 | dumpptr(L"%p", obj);
733 | }
734 | return hr;
735 | }
736 |
737 | virtual ULONG STDMETHODCALLTYPE AddRef() override {
738 | dbg(L"called from %p", _ReturnAddress());
739 | ULONG refcount = orig->AddRef();
740 | dump(L"%u", refcount);
741 | return refcount;
742 | }
743 |
744 | virtual ULONG STDMETHODCALLTYPE Release() override {
745 | dbg(L"called from %p", _ReturnAddress());
746 | ULONG refcount = orig->Release();
747 | dump(L"%u", refcount);
748 | if (!refcount) {
749 | delete this;
750 | }
751 | return refcount;
752 | }
753 |
754 | // IInspectable
755 |
756 | virtual HRESULT STDMETHODCALLTYPE
757 | GetIids(ULONG* n_iids, IID** iids) override
758 | {
759 | dbg(L"called from %p", _ReturnAddress());
760 | HRESULT hr = orig->GetIids(n_iids, iids);
761 | dump("%08X", hr);
762 | if (SUCCEEDED(hr)) {
763 | for (ULONG i = 0; i < *n_iids; ++i) {
764 | dumpiid((*iids)[i]);
765 | }
766 | }
767 | return hr;
768 | }
769 |
770 | virtual HRESULT STDMETHODCALLTYPE
771 | GetRuntimeClassName(HSTRING* name) override
772 | {
773 | dbg(L"called from %p", _ReturnAddress());
774 | HRESULT hr = orig->GetRuntimeClassName(name);
775 | dump("%08X", hr);
776 | if (SUCCEEDED(hr)) {
777 | dumpstr(*name);
778 | }
779 | return hr;
780 | }
781 |
782 | virtual HRESULT STDMETHODCALLTYPE GetTrustLevel(TrustLevel* l) override {
783 | dbg(L"called from %p", _ReturnAddress());
784 | HRESULT hr = orig->GetTrustLevel(l);
785 | dump("%08X", hr);
786 | if (SUCCEEDED(hr)) {
787 | char* level = "Unknown";
788 | switch (*l) {
789 | #define c(x) case x: level = #x; break
790 | c(BaseTrust);
791 | c(PartialTrust);
792 | c(FullTrust);
793 | #undef c
794 | }
795 | dump(L"%hs", level);
796 | }
797 | return hr;
798 | }
799 | };
800 |
801 | // ------------------------------------------------------------------------
802 |
803 | struct __declspec(uuid("4D239005-3C2A-41B1-9022-536BB9CF93B1"))
804 | _ICoreWindowStatic : public abi::ICoreWindowStatic {
805 | abi::ICoreWindowStatic* orig;
806 |
807 | explicit _ICoreWindowStatic(abi::ICoreWindowStatic* orig)
808 | : orig(orig)
809 | {
810 | dump("%p", orig);
811 | }
812 |
813 | // IUnknown
814 |
815 | virtual HRESULT STDMETHODCALLTYPE
816 | QueryInterface(REFIID riid, void** obj) override
817 | {
818 | dbg(L"called from %p", _ReturnAddress());
819 | dumpiid(riid);
820 | HRESULT hr = orig->QueryInterface(riid, obj);
821 | dump("%08X", hr);
822 | if (SUCCEEDED(hr)) {
823 | dumpptr(L"%p", obj);
824 | }
825 | return hr;
826 | }
827 |
828 | virtual ULONG STDMETHODCALLTYPE AddRef() override {
829 | dbg(L"called from %p", _ReturnAddress());
830 | ULONG refcount = orig->AddRef();
831 | dump(L"%u", refcount);
832 | return refcount;
833 | }
834 |
835 | virtual ULONG STDMETHODCALLTYPE Release() override {
836 | dbg(L"called from %p", _ReturnAddress());
837 | ULONG refcount = orig->Release();
838 | dump(L"%u", refcount);
839 | if (!refcount) {
840 | delete this;
841 | }
842 | return refcount;
843 | }
844 |
845 | // IInspectable
846 |
847 | virtual HRESULT STDMETHODCALLTYPE
848 | GetIids(ULONG* n_iids, IID** iids) override
849 | {
850 | dbg(L"called from %p", _ReturnAddress());
851 | HRESULT hr = orig->GetIids(n_iids, iids);
852 | dump("%08X", hr);
853 | if (SUCCEEDED(hr)) {
854 | for (ULONG i = 0; i < *n_iids; ++i) {
855 | dumpiid((*iids)[i]);
856 | }
857 | }
858 | return hr;
859 | }
860 |
861 | virtual HRESULT STDMETHODCALLTYPE
862 | GetRuntimeClassName(HSTRING* name) override
863 | {
864 | dbg(L"called from %p", _ReturnAddress());
865 | HRESULT hr = orig->GetRuntimeClassName(name);
866 | dump("%08X", hr);
867 | if (SUCCEEDED(hr)) {
868 | dumpstr(*name);
869 | }
870 | return hr;
871 | }
872 |
873 | virtual HRESULT STDMETHODCALLTYPE GetTrustLevel(TrustLevel* l) override {
874 | dbg(L"called from %p", _ReturnAddress());
875 | HRESULT hr = orig->GetTrustLevel(l);
876 | dump("%08X", hr);
877 | if (SUCCEEDED(hr)) {
878 | char* level = "Unknown";
879 | switch (*l) {
880 | #define c(x) case x: level = #x; break
881 | c(BaseTrust);
882 | c(PartialTrust);
883 | c(FullTrust);
884 | #undef c
885 | }
886 | dump(L"%hs", level);
887 | }
888 | return hr;
889 | }
890 |
891 | // ICoreWindowStatic
892 |
893 | virtual HRESULT STDMETHODCALLTYPE GetForCurrentThread(
894 | abi::ICoreWindow** pwindow) override
895 | {
896 | dbg(L"called from %p", _ReturnAddress());
897 | HRESULT hr = orig->GetForCurrentThread(pwindow);
898 | if (SUCCEEDED(hr)) {
899 | dumpptr("%p", pwindow);
900 | }
901 | dump("%08X", hr);
902 | return hr;
903 | }
904 | };
905 |
906 | // ------------------------------------------------------------------------
907 |
908 | struct __declspec(uuid("65A1ECC5-3FB5-4832-8CA9-F061B281D13A"))
909 | _IDeferralFactory : public abi::IDeferralFactory {
910 | abi::IDeferralFactory* orig;
911 |
912 | explicit _IDeferralFactory(abi::IDeferralFactory* orig)
913 | : orig(orig)
914 | {
915 | dump("%p", orig);
916 | }
917 |
918 | // IUnknown
919 |
920 | virtual HRESULT STDMETHODCALLTYPE
921 | QueryInterface(REFIID riid, void** obj) override
922 | {
923 | dbg(L"called from %p", _ReturnAddress());
924 | dumpiid(riid);
925 | HRESULT hr = orig->QueryInterface(riid, obj);
926 | dump("%08X", hr);
927 | if (SUCCEEDED(hr)) {
928 | dumpptr(L"%p", obj);
929 | }
930 | return hr;
931 | }
932 |
933 | virtual ULONG STDMETHODCALLTYPE AddRef() override {
934 | dbg(L"called from %p", _ReturnAddress());
935 | ULONG refcount = orig->AddRef();
936 | dump(L"%u", refcount);
937 | return refcount;
938 | }
939 |
940 | virtual ULONG STDMETHODCALLTYPE Release() override {
941 | dbg(L"called from %p", _ReturnAddress());
942 | ULONG refcount = orig->Release();
943 | dump(L"%u", refcount);
944 | if (!refcount) {
945 | delete this;
946 | }
947 | return refcount;
948 | }
949 |
950 | // IInspectable
951 |
952 | virtual HRESULT STDMETHODCALLTYPE
953 | GetIids(ULONG* n_iids, IID** iids) override
954 | {
955 | dbg(L"called from %p", _ReturnAddress());
956 | HRESULT hr = orig->GetIids(n_iids, iids);
957 | dump("%08X", hr);
958 | if (SUCCEEDED(hr)) {
959 | for (ULONG i = 0; i < *n_iids; ++i) {
960 | dumpiid((*iids)[i]);
961 | }
962 | }
963 | return hr;
964 | }
965 |
966 | virtual HRESULT STDMETHODCALLTYPE
967 | GetRuntimeClassName(HSTRING* name) override
968 | {
969 | dbg(L"called from %p", _ReturnAddress());
970 | HRESULT hr = orig->GetRuntimeClassName(name);
971 | dump("%08X", hr);
972 | if (SUCCEEDED(hr)) {
973 | dumpstr(*name);
974 | }
975 | return hr;
976 | }
977 |
978 | virtual HRESULT STDMETHODCALLTYPE GetTrustLevel(TrustLevel* l) override {
979 | dbg(L"called from %p", _ReturnAddress());
980 | HRESULT hr = orig->GetTrustLevel(l);
981 | dump("%08X", hr);
982 | if (SUCCEEDED(hr)) {
983 | char* level = "Unknown";
984 | switch (*l) {
985 | #define c(x) case x: level = #x; break
986 | c(BaseTrust);
987 | c(PartialTrust);
988 | c(FullTrust);
989 | #undef c
990 | }
991 | dump(L"%hs", level);
992 | }
993 | return hr;
994 | }
995 |
996 | // IDeferralFactory
997 |
998 | virtual HRESULT STDMETHODCALLTYPE Create(
999 | abi::IDeferralCompletedHandler* handler, abi::IDeferral** result)
1000 | override
1001 | {
1002 | dbg(L"called from %p", _ReturnAddress());
1003 | HRESULT hr = orig->Create(handler, result);
1004 | dump("%08X", hr);
1005 | if (SUCCEEDED(hr)) {
1006 | dumpptr("%p", result);
1007 | }
1008 | return hr;
1009 | }
1010 | };
1011 |
1012 | // ------------------------------------------------------------------------
1013 |
1014 | struct __declspec(uuid("50850B26-267E-451B-A890-AB6A370245EE"))
1015 | _IAsyncCausalityTracerStatics : public abi::IAsyncCausalityTracerStatics {
1016 | abi::IAsyncCausalityTracerStatics* orig;
1017 |
1018 | explicit _IAsyncCausalityTracerStatics(abi::IAsyncCausalityTracerStatics* orig)
1019 | : orig(orig)
1020 | {
1021 | dump("%p", orig);
1022 | }
1023 |
1024 | // IUnknown
1025 |
1026 | virtual HRESULT STDMETHODCALLTYPE
1027 | QueryInterface(REFIID riid, void** obj) override
1028 | {
1029 | dbg(L"called from %p", _ReturnAddress());
1030 | dumpiid(riid);
1031 | HRESULT hr = orig->QueryInterface(riid, obj);
1032 | dump("%08X", hr);
1033 | if (SUCCEEDED(hr)) {
1034 | dumpptr(L"%p", obj);
1035 | }
1036 | return hr;
1037 | }
1038 |
1039 | virtual ULONG STDMETHODCALLTYPE AddRef() override {
1040 | dbg(L"called from %p", _ReturnAddress());
1041 | ULONG refcount = orig->AddRef();
1042 | dump(L"%u", refcount);
1043 | return refcount;
1044 | }
1045 |
1046 | virtual ULONG STDMETHODCALLTYPE Release() override {
1047 | dbg(L"called from %p", _ReturnAddress());
1048 | ULONG refcount = orig->Release();
1049 | dump(L"%u", refcount);
1050 | if (!refcount) {
1051 | delete this;
1052 | }
1053 | return refcount;
1054 | }
1055 |
1056 | // IInspectable
1057 |
1058 | virtual HRESULT STDMETHODCALLTYPE
1059 | GetIids(ULONG* n_iids, IID** iids) override
1060 | {
1061 | dbg(L"called from %p", _ReturnAddress());
1062 | HRESULT hr = orig->GetIids(n_iids, iids);
1063 | dump("%08X", hr);
1064 | if (SUCCEEDED(hr)) {
1065 | for (ULONG i = 0; i < *n_iids; ++i) {
1066 | dumpiid((*iids)[i]);
1067 | }
1068 | }
1069 | return hr;
1070 | }
1071 |
1072 | virtual HRESULT STDMETHODCALLTYPE
1073 | GetRuntimeClassName(HSTRING* name) override
1074 | {
1075 | dbg(L"called from %p", _ReturnAddress());
1076 | HRESULT hr = orig->GetRuntimeClassName(name);
1077 | dump("%08X", hr);
1078 | if (SUCCEEDED(hr)) {
1079 | dumpstr(*name);
1080 | }
1081 | return hr;
1082 | }
1083 |
1084 | virtual HRESULT STDMETHODCALLTYPE GetTrustLevel(TrustLevel* l) override {
1085 | dbg(L"called from %p", _ReturnAddress());
1086 | HRESULT hr = orig->GetTrustLevel(l);
1087 | dump("%08X", hr);
1088 | if (SUCCEEDED(hr)) {
1089 | char* level = "Unknown";
1090 | switch (*l) {
1091 | #define c(x) case x: level = #x; break
1092 | c(BaseTrust);
1093 | c(PartialTrust);
1094 | c(FullTrust);
1095 | #undef c
1096 | }
1097 | dump(L"%hs", level);
1098 | }
1099 | return hr;
1100 | }
1101 |
1102 | // IAsyncCausalityTracerStatics
1103 |
1104 | static char const* TraceLevelStr(abi::CausalityTraceLevel trace_level) {
1105 | #define c(x) case x: return #x;
1106 | switch (trace_level) {
1107 | c(abi::CausalityTraceLevel_Required);
1108 | c(abi::CausalityTraceLevel_Important);
1109 | c(abi::CausalityTraceLevel_Verbose);
1110 | }
1111 | #undef c
1112 | return "?";
1113 | }
1114 |
1115 | static char const* SourceStr(abi::CausalitySource source) {
1116 | #define c(x) case x: return #x;
1117 | switch (source) {
1118 | c(abi::CausalitySource_Application);
1119 | c(abi::CausalitySource_Library);
1120 | c(abi::CausalitySource_System);
1121 | }
1122 | #undef c
1123 | return "?";
1124 | }
1125 |
1126 | static char const* AsyncStatusStr(AsyncStatus status) {
1127 | #define c(x) case x: return #x;
1128 | switch (status) {
1129 | c(Canceled);
1130 | c(Completed);
1131 | c(Error);
1132 | c(Started);
1133 | }
1134 | #undef c
1135 | return "?";
1136 | }
1137 |
1138 | static char const* CausalityRelationStr(abi::CausalityRelation rel) {
1139 | #define c(x) case x: return #x;
1140 | switch (rel) {
1141 | c(abi::CausalityRelation_AssignDelegate);
1142 | c(abi::CausalityRelation_Join);
1143 | c(abi::CausalityRelation_Choice);
1144 | c(abi::CausalityRelation_Cancel);
1145 | c(abi::CausalityRelation_Error);
1146 | }
1147 | #undef c
1148 | return "?";
1149 | }
1150 |
1151 | static char const* CausalitySynchronousWorkStr(
1152 | abi::CausalitySynchronousWork work) {
1153 | #define c(x) case x: return #x;
1154 | switch (work) {
1155 | c(abi::CausalitySynchronousWork_CompletionNotification);
1156 | c(abi::CausalitySynchronousWork_ProgressNotification);
1157 | c(abi::CausalitySynchronousWork_Execution);
1158 | }
1159 | #undef c
1160 | return "?";
1161 | }
1162 |
1163 | virtual HRESULT STDMETHODCALLTYPE TraceOperationCreation(
1164 | abi::CausalityTraceLevel trace_level, abi::CausalitySource source,
1165 | GUID platform_id, UINT64 operation_id,
1166 | HSTRING operation_name, UINT64 related_context) override
1167 | {
1168 | dbg(L"called from %p", _ReturnAddress());
1169 | dump(L"%hs", TraceLevelStr(trace_level));
1170 | dump(L"%hs", SourceStr(source));
1171 | dumpiid(platform_id);
1172 | dump("%I64d", operation_id);
1173 | dumpstr(operation_name);
1174 | dump("%I64u", related_context);
1175 | HRESULT hr = orig->TraceOperationCreation(trace_level, source,
1176 | platform_id, operation_id, operation_name, related_context);
1177 | dump("%08X", hr);
1178 | return hr;
1179 | }
1180 |
1181 | virtual HRESULT STDMETHODCALLTYPE TraceOperationCompletion(
1182 | abi::CausalityTraceLevel trace_level, abi::CausalitySource source,
1183 | GUID platform_id, UINT64 operation_id, AsyncStatus status) override
1184 | {
1185 | dbg(L"called from %p", _ReturnAddress());
1186 | dump(L"%hs", TraceLevelStr(trace_level));
1187 | dump(L"%hs", SourceStr(source));
1188 | dumpiid(platform_id);
1189 | dump("%I64d", operation_id);
1190 | dump(L"%hs", AsyncStatusStr(status));
1191 | HRESULT hr = orig->TraceOperationCompletion(trace_level, source,
1192 | platform_id, operation_id, status);
1193 | dump("%08X", hr);
1194 | return hr;
1195 | }
1196 |
1197 | virtual HRESULT STDMETHODCALLTYPE TraceOperationRelation(
1198 | abi::CausalityTraceLevel trace_level, abi::CausalitySource source,
1199 | GUID platform_id, UINT64 operation_id, abi::CausalityRelation relation)
1200 | override
1201 | {
1202 | dbg(L"called from %p", _ReturnAddress());
1203 | dump(L"%hs", TraceLevelStr(trace_level));
1204 | dump(L"%hs", SourceStr(source));
1205 | dumpiid(platform_id);
1206 | dump("%I64d", operation_id);
1207 | dump(L"%hs", CausalityRelationStr(relation));
1208 | HRESULT hr = orig->TraceOperationRelation(trace_level, source,
1209 | platform_id, operation_id, relation);
1210 | dump("%08X", hr);
1211 | return hr;
1212 | }
1213 |
1214 | virtual HRESULT STDMETHODCALLTYPE TraceSynchronousWorkStart(
1215 | abi::CausalityTraceLevel trace_level, abi::CausalitySource source,
1216 | GUID platform_id, UINT64 operation_id,
1217 | abi::CausalitySynchronousWork work) override
1218 | {
1219 | dbg(L"called from %p", _ReturnAddress());
1220 | dump(L"%hs", TraceLevelStr(trace_level));
1221 | dump(L"%hs", SourceStr(source));
1222 | dumpiid(platform_id);
1223 | dump("%I64d", operation_id);
1224 | dump(L"%hs", CausalitySynchronousWorkStr(work));
1225 | HRESULT hr = orig->TraceSynchronousWorkStart(trace_level, source,
1226 | platform_id, operation_id, work);
1227 | dump("%08X", hr);
1228 | return hr;
1229 | }
1230 |
1231 | virtual HRESULT STDMETHODCALLTYPE TraceSynchronousWorkCompletion(
1232 | abi::CausalityTraceLevel trace_level, abi::CausalitySource source,
1233 | abi::CausalitySynchronousWork work) override
1234 | {
1235 | dbg(L"called from %p", _ReturnAddress());
1236 | dump(L"%hs", TraceLevelStr(trace_level));
1237 | dump(L"%hs", SourceStr(source));
1238 | dump(L"%hs", CausalitySynchronousWorkStr(work));
1239 | HRESULT hr =
1240 | orig->TraceSynchronousWorkCompletion(trace_level, source, work);
1241 | dump("%08X", hr);
1242 | return hr;
1243 | }
1244 |
1245 | virtual HRESULT STDMETHODCALLTYPE add_TracingStatusChanged(
1246 | abi::IEventHandler* handler,
1247 | EventRegistrationToken* cookie) override
1248 | {
1249 | dbg(L"called from %p", _ReturnAddress());
1250 | HRESULT hr = orig->add_TracingStatusChanged(handler, cookie);
1251 | dump("%08X", hr);
1252 | return hr;
1253 | }
1254 |
1255 | virtual HRESULT STDMETHODCALLTYPE remove_TracingStatusChanged(
1256 | EventRegistrationToken cookie) override
1257 | {
1258 | dbg(L"called from %p", _ReturnAddress());
1259 | HRESULT hr = orig->remove_TracingStatusChanged(cookie);
1260 | dump("%08X", hr);
1261 | return hr;
1262 | }
1263 | };
1264 |
1265 | // ------------------------------------------------------------------------
1266 |
1267 | HRESULT (STDMETHODCALLTYPE* orig_RoGetActivationFactory)(
1268 | HSTRING id, REFIID iid, void** pfactory);
1269 |
1270 | STDAPI _RoGetActivationFactory(HSTRING id, REFIID iid, void** pfactory) {
1271 | HRESULT hr;
1272 | void* res;
1273 | dbg(L"called from %p", _ReturnAddress());
1274 | dumpstr(id);
1275 | dumpiid(iid);
1276 | hr = orig_RoGetActivationFactory(id, iid, &res);
1277 | dump("%08X", hr);
1278 | if (FAILED(hr)) {
1279 | *pfactory = res;
1280 | } else if (iid == __uuidof(IActivationFactory)) {
1281 | *pfactory = new _IActivationFactory((IActivationFactory*)res);
1282 | } else if (iid == __uuidof(abi::ICoreApplication)) {
1283 | *pfactory = new _ICoreApplication((abi::ICoreApplication*)res);
1284 | } else if (iid == __uuidof(abi::ICoreWindowStatic)) {
1285 | *pfactory = new _ICoreWindowStatic((abi::ICoreWindowStatic*)res);
1286 | } else if (iid == __uuidof(abi::IDeferralFactory)) {
1287 | *pfactory = new _IDeferralFactory((abi::IDeferralFactory*)res);
1288 | } else if (iid == __uuidof(abi::IAsyncCausalityTracerStatics)) {
1289 | *pfactory = new _IAsyncCausalityTracerStatics(
1290 | (abi::IAsyncCausalityTracerStatics*)res);
1291 | } else {
1292 | *pfactory = res;
1293 | }
1294 | return hr;
1295 | }
1296 |
1297 | // ------------------------------------------------------------------------
1298 |
1299 | HRESULT (STDMETHODCALLTYPE* orig_RoActivateInstance)
1300 | (HSTRING id, IInspectable** instance);
1301 |
1302 | STDAPI _RoActivateInstance(HSTRING id, IInspectable** instance) {
1303 | IInspectable* res;
1304 | HRESULT hr;
1305 | PCWSTR s;
1306 | dbg(L"called from %p", _ReturnAddress());
1307 | dumpstr(id);
1308 | hr = orig_RoActivateInstance(id, &res);
1309 | dump("%08X", hr);
1310 | s = _WindowsGetStringRawBuffer(id, 0);
1311 | if (FAILED(hr)) {
1312 | *instance = res;
1313 | } else if (!wcscmp(s, L"Windows.Foundation.Collections.PropertySet")) {
1314 | *instance = new _IPropertySet((abi::IPropertySet*)res);
1315 | } else {
1316 | *instance = res;
1317 | }
1318 | if (SUCCEEDED(hr)) {
1319 | dumpptr("%p", instance);
1320 | }
1321 | return hr;
1322 | }
1323 |
1324 | // ------------------------------------------------------------------------
1325 |
1326 | HRESULT (STDMETHODCALLTYPE* orig_RoGetApartmentIdentifier)
1327 | (UINT64* identifier);
1328 |
1329 | STDAPI _RoGetApartmentIdentifier(UINT64* identifier) {
1330 | HRESULT hr;
1331 | dbg(L"called from %p", _ReturnAddress());
1332 | hr = orig_RoGetApartmentIdentifier(identifier);
1333 | dump("%08X", hr);
1334 | if (SUCCEEDED(hr)) {
1335 | dumpptr("%I64d", identifier);
1336 | }
1337 | return hr;
1338 | }
1339 |
1340 | // ------------------------------------------------------------------------
1341 |
1342 | HRESULT (STDMETHODCALLTYPE* orig_RoInitialize)(RO_INIT_TYPE t);
1343 |
1344 | STDAPI _RoInitialize(RO_INIT_TYPE t) {
1345 | HRESULT hr;
1346 | dbg(L"called from %p", _ReturnAddress());
1347 | #define c(x) case x: dbg(L"" #x)
1348 | switch (t) {
1349 | c(RO_INIT_SINGLETHREADED); break;
1350 | c(RO_INIT_MULTITHREADED); break;
1351 | }
1352 | #undef c
1353 | hr = orig_RoInitialize(t);
1354 | dump("%08X", hr);
1355 | return hr;
1356 | }
1357 |
1358 | // ------------------------------------------------------------------------
1359 |
1360 | HRESULT (STDMETHODCALLTYPE* orig_RoRegisterActivationFactories)(
1361 | HSTRING* ids, PFNGETACTIVATIONFACTORY* callbacks, UINT32 count,
1362 | RO_REGISTRATION_COOKIE* cookie);
1363 |
1364 | STDAPI _RoRegisterActivationFactories(HSTRING* ids,
1365 | PFNGETACTIVATIONFACTORY* callbacks, UINT32 count,
1366 | RO_REGISTRATION_COOKIE* cookie)
1367 | {
1368 | HRESULT hr;
1369 | UINT32 i;
1370 | dbg(L"called from %p", _ReturnAddress());
1371 | for (i = 0; i < count; ++i) {
1372 | dumpstr(ids[i]);
1373 | dump("%p", callbacks[i]);
1374 | }
1375 | dump("%p", cookie);
1376 | hr = orig_RoRegisterActivationFactories(ids, callbacks, count, cookie);
1377 | dump("%08X", hr);
1378 | return hr;
1379 | }
1380 |
1381 | // ------------------------------------------------------------------------
1382 |
1383 | HRESULT (STDMETHODCALLTYPE* orig_RoRegisterForApartmentShutdown)(
1384 | IApartmentShutdown* obj, UINT64* identifier,
1385 | APARTMENT_SHUTDOWN_REGISTRATION_COOKIE* cookie);
1386 |
1387 | STDAPI _RoRegisterForApartmentShutdown(IApartmentShutdown* obj,
1388 | UINT64* identifier, APARTMENT_SHUTDOWN_REGISTRATION_COOKIE* cookie)
1389 | {
1390 | HRESULT hr;
1391 | dbg(L"called from %p", _ReturnAddress());
1392 | dump("%p", obj);
1393 | hr = orig_RoRegisterForApartmentShutdown(obj, identifier, cookie);
1394 | dump("%08X", hr);
1395 | if (SUCCEEDED(hr)) {
1396 | dumpptr("%I64d", identifier);
1397 | dump("%p", cookie);
1398 | }
1399 | return hr;
1400 | }
1401 |
1402 | // ------------------------------------------------------------------------
1403 |
1404 | void (STDMETHODCALLTYPE* orig_RoRevokeActivationFactories)
1405 | (RO_REGISTRATION_COOKIE cookie);
1406 |
1407 | STDAPI_(void) _RoRevokeActivationFactories(RO_REGISTRATION_COOKIE cookie) {
1408 | dbg(L"called from %p", _ReturnAddress());
1409 | dump("%p", cookie);
1410 | orig_RoRevokeActivationFactories(cookie);
1411 | }
1412 |
1413 | // ------------------------------------------------------------------------
1414 |
1415 | void (STDMETHODCALLTYPE* orig_RoUninitialize)();
1416 |
1417 | STDAPI_(void) _RoUninitialize() {
1418 | dbg(L"called from %p", _ReturnAddress());
1419 | orig_RoUninitialize();
1420 | }
1421 |
1422 | // ------------------------------------------------------------------------
1423 |
1424 | HRESULT (STDMETHODCALLTYPE* orig_RoUnregisterForApartmentShutdown)
1425 | (APARTMENT_SHUTDOWN_REGISTRATION_COOKIE cookie);
1426 |
1427 | STDAPI _RoUnregisterForApartmentShutdown(
1428 | APARTMENT_SHUTDOWN_REGISTRATION_COOKIE cookie)
1429 | {
1430 | HRESULT hr;
1431 | dbg(L"called from %p", _ReturnAddress());
1432 | dump("%p", cookie);
1433 | hr = orig_RoUnregisterForApartmentShutdown(cookie);
1434 | dump("%08X", hr);
1435 | return hr;
1436 | }
1437 |
1438 | // ------------------------------------------------------------------------
1439 |
1440 | #define h(x, nops) { #x, _##x, (void**)&orig_##x, nops }
1441 | #define t(x) { #x, 0, (void**)&_##x, 0 }
1442 | spy_export_t hooks[] = {
1443 | t(WindowsGetStringRawBuffer),
1444 | h(RoActivateInstance, 0),
1445 | h(RoGetActivationFactory, 1),
1446 | h(RoGetApartmentIdentifier, 0),
1447 | h(RoInitialize, 1),
1448 | h(RoRegisterActivationFactories, 0),
1449 | h(RoRegisterForApartmentShutdown, 0),
1450 | h(RoRevokeActivationFactories, 1),
1451 | h(RoUninitialize, 0),
1452 | h(RoUnregisterForApartmentShutdown, 1),
1453 | };
1454 | #undef h
1455 |
1456 | void spy_init() {
1457 | log_init();
1458 | spy_exports("api-ms-win-core-winrt-l1-1-0.dll", _countof(hooks), hooks);
1459 | }
1460 |
1461 | /*
1462 | * NOTE: it's not a good idea to do complex init in DllMain but I don't
1463 | * wanna have spinlocks in every hook to wait in case the init thread
1464 | * hasn't finished
1465 | */
1466 |
1467 | BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved) {
1468 | (void)reserved;
1469 | (void)hinst;
1470 | if (reason == DLL_PROCESS_ATTACH) {
1471 | spy_init();
1472 | }
1473 | return TRUE;
1474 | }
1475 |
--------------------------------------------------------------------------------
/vcvarsall17.ps1:
--------------------------------------------------------------------------------
1 | # https://stackoverflow.com/questions/2124753/how-can-i-use-powershell-with-the-visual-studio-command-prompt
2 |
3 | param ([string]$arch = "amd64")
4 |
5 | Push-Location "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\Common7\Tools"
6 | cmd /c "VsDevCmd.bat -arch=$arch&set" |
7 | ForEach-Object {
8 | if ($_ -match "=") {
9 | $v = $_.Split("=")
10 | Set-Item -Force -Path "ENV:\$($v[0])" -Value "$($v[1])"
11 | }
12 | }
13 | Pop-Location
14 | $oldcolor = $host.UI.RawUI.ForegroundColor
15 | $host.UI.RawUI.ForegroundColor = "Green"
16 | Write-Output ":: Visual Studio 2017 Command Prompt variables set"
17 | $host.UI.RawUI.ForegroundColor = $oldcolor
18 |
--------------------------------------------------------------------------------