Sure, because most people wouldn't find them useful.
You'll find you're wrong on the "there's no code behind the switches."
Code:
.text:004043C9 loc_4043C9: ; CODE XREF: wWinMain(x,x,x,x)+212j
.text:004043C9 mov eax, [ebp+var_C]
.text:004043CC mov esi, [ebp+eax*4+lpString1]
.text:004043D0 push offset String2 ; "/ShowWU"
.text:004043D5 push esi ; lpString1
.text:004043D6 call ?AsciiStringCompareI@@YGJPBG0@Z ; AsciiStringCompareI(ushort const *,ushort const *)
.text:004043DB test eax, eax
.text:004043DD jz loc_4045DB
.text:004043E3 push offset aShowwindowsupd ; "/ShowWindowsUpdate"
.text:004043E8 push esi ; lpString1
.text:004043E9 call ?AsciiStringCompareI@@YGJPBG0@Z ; AsciiStringCompareI(ushort const *,ushort const *)
.text:004043EE test eax, eax
.text:004043F0 jz loc_4045DB
.text:004043F6 push offset aClosewindowsup ; "/CloseWindowsUpdate"
.text:004043FB push esi ; lpString1
.text:004043FC call ?AsciiStringCompareI@@YGJPBG0@Z ; AsciiStringCompareI(ushort const *,ushort const *)
.text:00404401 test eax, eax
.text:00404403 jz loc_40456E
.text:00404409 push offset aSelfupdateunma ; "/SelfUpdateUnmanaged"
.text:0040440E push esi ; lpString1
.text:0040440F call ?AsciiStringCompareI@@YGJPBG0@Z ; AsciiStringCompareI(ushort const *,ushort const *)
.text:00404414 test eax, eax
.text:00404416 jz loc_404578
.text:0040441C push offset aSelfupdatemana ; "/SelfUpdateManaged"
.text:00404421 push esi ; lpString1
.text:00404422 call ?AsciiStringCompareI@@YGJPBG0@Z ; AsciiStringCompareI(ushort const *,ushort const *)
.text:00404427 test eax, eax
.text:00404429 jz loc_404592
.text:0040442F push offset aDetectnow ; "/DetectNow"
.text:00404434 push esi ; lpString1
.text:00404435 call ?AsciiStringCompareI@@YGJPBG0@Z ; AsciiStringCompareI(ushort const *,ushort const *)
.text:0040443A test eax, eax
.text:0040443C jz loc_404599
.text:00404442 push offset aReportnow ; "/ReportNow"
.text:00404447 push esi ; lpString1
.text:00404448 call ?AsciiStringCompareI@@YGJPBG0@Z ; AsciiStringCompareI(ushort const *,ushort const *)
.text:0040444D test eax, eax
.text:0040444F jz loc_4045A0
.text:00404455 push offset aUpdatenow ; "/UpdateNow"
.text:0040445A push esi ; lpString1
.text:0040445B call ?AsciiStringCompareI@@YGJPBG0@Z ; AsciiStringCompareI(ushort const *,ushort const *)
.text:00404460 test eax, eax
.text:00404462 jz loc_4045A7
.text:00404468 push offset aRunhandlercoms ; "/RunHandlerComServer"
.text:0040446D push esi ; lpString1
.text:0040446E call ?AsciiStringCompareI@@YGJPBG0@Z ; AsciiStringCompareI(ushort const *,ushort const *)
.text:00404473 test eax, eax
.text:00404475 jz loc_4045AE
.text:0040447B push offset aRunstoreascoms ; "/RunStoreAsComServer"
.text:00404480 push esi ; lpString1
.text:00404481 call ?AsciiStringCompareI@@YGJPBG0@Z ; AsciiStringCompareI(ushort const *,ushort const *)
.text:00404486 test eax, eax
.text:00404488 jz loc_4045B5
.text:0040448E push offset aResetauthoriza ; "/ResetAuthorization"
.text:00404493 push esi ; lpString1
.text:00404494 call ?AsciiStringCompareI@@YGJPBG0@Z ; AsciiStringCompareI(ushort const *,ushort const *)
.text:00404499 test eax, eax
.text:0040449B jnz short loc_4044BC
.text:0040449D cmp ebx, 2
.text:004044A0 jnb loc_4045CB
.text:004044A6 cmp [ebp+var_18], eax
You see at each stop it's comparing a parameter against each of these and doing a jump if it matches.
Those jumps go to a dispatch table down further in the code:
Code:
.text:00404599 ; ---------------------------------------------------------------------------
.text:00404599
.text:00404599 loc_404599: ; CODE XREF: wWinMain(x,x,x,x)+FDj
.text:00404599 call ?DetectNow@@YGJXZ ; DetectNow(void)
.text:0040459E jmp short loc_404557
.text:004045A0 ; ---------------------------------------------------------------------------
.text:004045A0
.text:004045A0 loc_4045A0: ; CODE XREF: wWinMain(x,x,x,x)+110j
.text:004045A0 call ?ReportNow@@YGJXZ ; ReportNow(void)
.text:004045A5 jmp short loc_404557
.text:004045A7 ; ---------------------------------------------------------------------------
.text:004045A7
.text:004045A7 loc_4045A7: ; CODE XREF: wWinMain(x,x,x,x)+123j
.text:004045A7 call ?UpdateNow@@YGJXZ ; UpdateNow(void)
.text:004045AC jmp short loc_404557
.text:004045AE ; ---------------------------------------------------------------------------
.text:004045AE
.text:004045AE loc_4045AE: ; CODE XREF: wWinMain(x,x,x,x)+136j
.text:004045AE call ?RunUpdateHandler@@YGJXZ ; RunUpdateHandler(void)
.text:004045B3 jmp short loc_404626
.text:004045B5 ; ---------------------------------------------------------------------------
.text:004045B5
.text:004045B5 loc_4045B5: ; CODE XREF: wWinMain(x,x,x,x)+149j
.text:004045B5 mov eax, [ebp+var_C]
.text:004045B8 lea ecx, [eax+1]
.text:004045BB cmp ecx, [ebp+var_20]
.text:004045BE jnb short loc_4045CB
.text:004045C0 push [ebp+eax*4+hLibModule] ; hLibModule
.text:004045C4 call ?RunDatastoreAsComServer@@YGJPBG@Z ; RunDatastoreAsComServer(ushort const *)
.text:004045C9 jmp short loc_404626
Etc. To see what they do, you can follow their code. Let's start with one we "know" works (DetectNow):
Code:
.text:00403EC0 ; long __stdcall DetectNow(void)
.text:00403EC0 ?DetectNow@@YGJXZ proc near ; CODE XREF: wWinMain(x,x,x,x):loc_404599p
.text:00403EC0
.text:00403EC0 ppv = dword ptr -4
.text:00403EC0
.text:00403EC0 mov edi, edi
.text:00403EC2 push ebp
.text:00403EC3 mov ebp, esp
.text:00403EC5 push ecx
.text:00403EC6 push esi
.text:00403EC7 push edi
.text:00403EC8 xor esi, esi
.text:00403ECA push esi ; dwCoInit
.text:00403ECB push esi ; pvReserved
.text:00403ECC call ds:__imp__CoInitializeEx@8 ; CoInitializeEx(x,x)
.text:00403ED2 push 3
.text:00403ED4 mov edi, eax
.text:00403ED6 call ?RegisterProxyStubCLSIDs@@YGXK@Z ; RegisterProxyStubCLSIDs(ulong)
.text:00403EDB cmp edi, esi
.text:00403EDD jl short loc_403F13
.text:00403EDF lea eax, [ebp+ppv]
.text:00403EE2 push eax ; ppv
.text:00403EE3 push offset __GUID_7ae22377_b19d_497d_808e_307860c5660a ; riid
.text:00403EE8 mov [ebp+ppv], esi
.text:00403EEB call ?CoCreateAU@@YGJABU_GUID@@PAPAX@Z ; CoCreateAU(_GUID const &,void * *)
.text:00403EF0 mov edi, eax
.text:00403EF2 cmp edi, esi
.text:00403EF4 jl short loc_403F0D
.text:00403EF6 mov eax, [ebp+ppv]
.text:00403EF9 mov ecx, [eax]
.text:00403EFB push esi
.text:00403EFC push esi
.text:00403EFD push esi
.text:00403EFE push eax
.text:00403EFF call dword ptr [ecx+5Ch]
.text:00403F02 mov edi, eax
.text:00403F04 mov eax, [ebp+ppv]
.text:00403F07 mov ecx, [eax]
.text:00403F09 push eax
.text:00403F0A call dword ptr [ecx+8]
.text:00403F0D
.text:00403F0D loc_403F0D: ; CODE XREF: DetectNow(void)+34j
.text:00403F0D call ds:__imp__CoUninitialize@0 ; CoUninitialize()
.text:00403F13
.text:00403F13 loc_403F13: ; CODE XREF: DetectNow(void)+1Dj
.text:00403F13 mov eax, edi
.text:00403F15 pop edi
.text:00403F16 pop esi
.text:00403F17 leave
.text:00403F18 retn
.text:00403F18 ?DetectNow@@YGJXZ endp
So it calls CoInitializeEx(NULL,NULL), which initializes the COM lib in multithreaded mode, then registers some files with the system. The CoCreateAU is a function almost every switch that "does something" calls, it creates a COM AutomaticUpdates object and returns the result of the CoCreateInstance call. This COM object has GUID string: "__GUID_7ae22377_b19d_497d_808e_307860c5660a". You could always create an instance of this object yourself and play around with what it can do, I may reverse the DLLs responsible for implementing its functionality at some point and see if I can document these switches. The 'ReportNow' uses a different GUID, so it seems there's a windows update and a windows update reporting COM differentiation.
You can see after it gets that HRESULT back, it compares it against 0 (esi is used as zero here, as by the ABI it must be preserved across interfacing function calls), if it's 0 it uninits the COM library and returns false. Otherwise it calls some thiscall function in the class instance returned as a pointer from the CoCreateAU call.
The switches do work similarly through COM. The base API in the wuaueng.dll though is particularly interesting.
Bookmarks