From 9b58d9a908a45a55452b87d001789d27fbf0e8ee Mon Sep 17 00:00:00 2001 From: andylsn Date: Tue, 24 Mar 2020 16:38:30 -0700 Subject: [PATCH] =?UTF-8?q?Rewrite=20the=20service=20for=20the=20best=20pr?= =?UTF-8?q?actice=20of=20Win32=20Services=20Interacti=E2=80=A6=20(#472)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Rewrite the service for the best practice of Win32 Services Interacting with Devices * Rewrite the service using pure WIN32 APIs * Support multiple device interfaces * Add WINAPI decoration to notification callbacks to avoid AV issue * A small fix * Implement OSRFX2 samples for AddTrigger syntax and service lifetime control * Add comment on AddTrigger syntax Co-authored-by: Shunni Li * Update inx file (#2) Co-authored-by: Shunni Li * Add PnpLockdown in INX * Update osrfx2_DCHU_base.inx Co-authored-by: Shunni Li --- .../osrfx2_DCHU_base/osrfx2_DCHU_base.inx | Bin 10266 -> 4248 bytes .../osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj | 2 +- .../osrfx2_DCHU_filter.vcxproj | 2 +- .../osrfx2_DCHU_testapp/osrusbfx2.vcxproj | 2 +- .../osrfx2_DCHU_usersvc/CppWindowsService.cpp | 74 - .../osrfx2_DCHU_usersvc/DeviceContext.cpp | 856 ++++++++++++ .../osrfx2_DCHU_usersvc/DeviceContext.h | 155 +++ .../osrfx2_DCHU_usersvc/DeviceControl.cpp | 192 +++ .../osrfx2_DCHU_usersvc/DeviceControl.h | 144 ++ .../osrfx2_DCHU_usersvc/Main.cpp | 1217 ----------------- .../osrfx2_DCHU_usersvc/Main.h | 328 ----- .../osrfx2_DCHU_usersvc/SampleService.cpp | 254 ---- .../osrfx2_DCHU_usersvc/SampleService.h | 187 --- .../osrfx2_DCHU_usersvc/ServiceBase.cpp | 794 ----------- .../osrfx2_DCHU_usersvc/ServiceBase.h | 423 ------ .../osrfx2_DCHU_usersvc/ServiceWin32API.cpp | 375 +++++ .../osrfx2_DCHU_usersvc/ServiceWin32API.h | 56 + .../osrfx2_DCHU_usersvc/ThreadPool.h | 80 -- .../osrfx2_DCHU_usersvc/Utils.cpp | 156 --- .../osrfx2_DCHU_usersvc/Utils.h | 111 -- .../osrfx2_DCHU_usersvc.inx | Bin 3190 -> 0 bytes .../osrfx2_DCHU_usersvc.vcxproj | 30 +- .../osrfx2_DCHU_usersvc/stdafx.h | 26 + 23 files changed, 1820 insertions(+), 3644 deletions(-) delete mode 100644 general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/CppWindowsService.cpp create mode 100644 general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.cpp create mode 100644 general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.h create mode 100644 general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.cpp create mode 100644 general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.h delete mode 100644 general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.cpp delete mode 100644 general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.h delete mode 100644 general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.cpp delete mode 100644 general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.h delete mode 100644 general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.cpp delete mode 100644 general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.h create mode 100644 general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.cpp create mode 100644 general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.h delete mode 100644 general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ThreadPool.h delete mode 100644 general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.cpp delete mode 100644 general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.h delete mode 100644 general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.inx create mode 100644 general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/stdafx.h diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.inx b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.inx index 8271e39daa64491d186178572059852907b10d0d..73b6d10e4e2fe67257539daa6b1a279c477c6609 100644 GIT binary patch literal 4248 zcmd5=-EQJa626a=cW9wub$)=shGf`{=EB$}u>uC!CONa4Bg@zgSOMGHHY8{?@3QZ4 zE{?P>w6CyV+ifs`oH-YJu~wwS-Bn*zeO=X6&VPRU{pRCOKmUAraf2TNzA+~jH4DI%4$V&sgy99QnsZ*tI#KeICq9k)Ul=$#ngyl4#w6< zag4D^us*TI4~C{|q^8(-uaQT?xf@R%@~BvrVme>QcmTaGKm*jhVQLMcLqxZT{>#MD zZ5z5{ix{KH(9p4InCft<8RjkN1H~LWWN3^G2U5-$uIL4j5HGD5y3Os3bW6R1QKfGT z4VZ?%AAvnE9215J9488yD3)WW)1hJ&P?M=O8QZ#ucN7Pk6(y#(rhnTrK;o3mUu9QQ z@22j|OKA%%6uZhS&6wwB6=5SvGjFxZxg}vVC-az*Y)Q#DWn}OwlOgq36h;ejA7%wg zv-#7<%Ztm4e>_l@;z)kIys*PXVts1&HM$Lb zDwb|HVSweYy?~$DaG(esK?7I=P8HxS z=6R)-je188aW9l05O1*mIMoJL&>-#CHh-kK*C^IBR|pBqg`0zww}7lnQktd6_b??M z|4p%w8`#%DAaeG|T9tf3a04d`U3=@lG5Ag(caKE~7G1!75j~9H{T+?RU=Ee(I+!Cx z5-;+KEjTMS{JO_ai zM+7qrXUtC;m1k^_gvK_W-b*WQ-iq8}VE*m7;!O*eW|1)#* zeYG77T5r<~*7zx{ydAGFxLtqT1am8>ETXzZY|bv>BJEd+XXhV2H^kPh2Se4}d)+ei zp{rR2xB^t>v1|{NSK}W7@nS8ZG<}5b?rnm^&y0ZF&4vE`b) z=?=+0zWv$NCAt1olxi#8rNV2$&{J_|JQYOcXL-J&PPr9w-yygC9YQLMJQ`+4cE^vV ziLJ5kji$ti!$$(;Hr$H)sA>u zFI;&u^xH5ZWy_b^q%35)-R=@E3Wzt0w?z*)wTYt?)>sZF^t!}x_mx=Cb zdR`ZX>FCx#L4{zbGai&70{40ILN5Oq^qhr5MwccOl~0jwSu&zl?9EI#Uca59mvbNX z_Q$q0_(iTC(|SXU2-hpd7fQGa?g@-8Mn>20Pi~Of+4-P$1aj(~rZ`H$f(?hw+iD9b znhKb{ySEwyPQl1Hp?sc>78oIE4ZW+T(Yd!-Wi=GRV0h~)nr7*@0`l+YbtfM4)@iP7 z#u0r__0atH{T|MoyTFfE5BKcx`cY2vvH0`bN3_!l)1v7WWA0n=>O04C_&AVy>jb$i z<^xLnO`64P;(LiV3s+&bBMFNaAOM&?Cg>e613p0bV3fQpLx0J!u){~;vOa);A=yik zG#@aE;eyXgo{ynMOd?`6+~-NQWbtOP#D#iOBDIPkGi|AbUlE_<5+qgeX>j2DFmSc@ zi6^F~{W~)6{q#k0h{*wov{$*j`1ijKMyfl%!cDwmUPq3BrgFI1tGdK&J37 zLxRGZ-0NT5BJ6|cG{QGv#zH@%fs!O@c|0La$q!t~8c(W);SLSk`7sCm+Lo{Bm2^#; zv!2v#cBSsD+3Wa0vv+kJT+ive+mq#Q4btONrQDWeFj2otJqHF0*7w$S=;dI;h9l8} zvs?YF5bdot@MbK0_STph-VWLzsb&`mCkE%Egw4gFb}~Y6y)w0g;vn8cL6PUpd?IbG zc|w-ENLcz3vu9$_`HK2TN8pNkxzav4aJ523%|W)vh2j{>$oRlUwlX;mfqzLt`s6E; zyoA{jAFX0+1?GEKC->s()u)c$Q$KZ@ZMBb6>VA@%iqs!82TEVQRy&f`>2<#WU*uQ&F#rGn literal 10266 zcmd6tYfl?j8pqG;mG(PWR#*FYWKmxjV<#wpk%4BjafQHK!g5^z82cFcA=-i$Yq|_tX<>RY43y|Y1J%^FEdI# zf>-AMEl+~q30wT@y}_I=ziYg|qoo6U$M-Iw&8d3BOwsV1-c|yo#Z0~Z%P_aVv60{v zg~GZ@&kFydMl%JYNy`@RdVWRQVnWLrxJ8r3uX1lDur_ITskCww<)IJrBAnvf`B~+y z3+C4erwyE|&aEh` ztLO<+iGH%`<+T)ZXDZQ1am}n} z3;avSTTya>yN^DUYZYbA`Q0;Wlof@chmKEaJ1`07F>TSWQ5zHApy9A1G=jk0CB`l+@S-*?8@8b0#G*{u(D-Vy5QI8Geyf@V6w7f+N z(pi^&`Q0>@D8KS+#^RdV({b{>JeIuoM(rQq4Lg=O1XDRhI=$l8vyS|;WU(jBLay}~ z-$%2QVsGq~T#ETB^4PrRjdDD1oO=XvYTO1V^ZYO!y+)dDT~2=&u9RUFH}ZCs?N9l= z-}r6puY*TEjJCJtkxpIoPmiS+=;{ieR=uFgLDVV|DT2tSJz@)6oR_zfyuD@l%-UDB zeb_I*1h&U2kI+SUvSaR#vx5|5k5LxUL$Vy)2V<(AaS(>-$!lf>+3!MuDz%%T>dWQ* z3~hK+{?Y2=4YH@!6Q0}i8d^+pfnfRUa+o5M)%aDkb~rs^>HRXO*Ky+S{cZfnN@tSX z|DX9hKu#yvy>uV5{y1K{MApf1!?}$9rFeN`KBYB-YhVh=U7JrTLXRKmSv{}IO(0#| zLh))uc~F*eMU|cHty_#}(W4so((=|Bqx5!?&=Dbs=NN%U?IpFAXv?CyioM)$%Mwx= zVin_j_TWvmidP4{9M`Fb#$vNx^J*Ljvk|7~`1U%cyP(OP8>GPu{U+%xc(!T1oYl8eTB-c@xHcX*Vc zRk6q`6djL&E}M?E?Eo+BbE)bcz_++Qv5~4f<6OxsRyz@ws;3Iv%iH37QLu@me1B+_ z|LENgVU_nbBh)V5FTkb!0>OMgp@xVxL8{xP>9hfa3tLz963k0RzgG}h+*P!;!u6bS zagH=z4xd?5OQ$oep4;eBYwB69Hfw0DxWDJt+PgtZjrIyHFKvzflA5bYuh!~I^!x%e zaUvTSrSCEEh;q^H(k|k8lp5)#XtZkZqg$PH$j|>lH`=R-*oyk4?YQUhSU7vYT!A93 znInElu!a_z+;z0jMiQKr=vAiuD;TYeyj|#h(*_-D&~6SiY75j8Dx%LW&H-@wEJFRtg=Rp zw>kP%4Jh}t#$=GEyUV&Czx@C9#4C3?is z0k^M_bYd{zO(*mz#V$iX7uD|CH8l54D=`B_3N=R(+T~a0Zl4l(s>D44=;UAU`t)m$ zMbFxY6&;GlAE85?PN;ui-wLQlXN?+r3UuvTq`Fl+*J|#VHhoEu%1yKmYu%wZ z=jn=4*;Tvtk*d5zo2GeXj?@Cn$qLXVFuV?2hT_zV{ER~<%)>g5X9f!i{?QR}Z}2mD z=oR~dejcaq5%gVx&JcAH-)4T3r){#9b`IKnL!g~Rtr?U@@}BR!j^Yw8zb00f=cs7L zPq)(c5gyTfzry`=c%QupQZ-uvYGNKM@N9bH*F73rS3)(n0r`rK!AGz=l0WlvlD F`U4=xIM)CG diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj index 57439bd94..f78f16b44 100644 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_base/osrfx2_DCHU_base.vcxproj @@ -26,7 +26,7 @@ Win32 {F915ED95-7BE9-4CDB-B09A-0D3F4C9657FE} osrfx2_DCHU_base - 10.0.15063.0 + 10.0.17134.0 diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj index 36d855833..09724ba57 100644 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_filter/osrfx2_DCHU_filter.vcxproj @@ -27,7 +27,7 @@ Debug Win32 {1A4A32BA-1596-4F52-BC48-B85A6D8D5D12} - 10.0.15063.0 + 10.0.17134.0 osrfx2_DCHU_filter diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj index 225dcde26..bc56feacf 100644 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_testapp/osrusbfx2.vcxproj @@ -25,7 +25,7 @@ Win32 {F19E45AF-8B05-4204-A66B-9BDBFE333233} osrfx2_DCHU_testapp - 10.0.15063.0 + 10.0.17134.0 diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/CppWindowsService.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/CppWindowsService.cpp deleted file mode 100644 index 98a3975c9..000000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/CppWindowsService.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - CppWindowsService.cpp - -Abstract: - - The file defines the entry point of the application. According to the - arguments in the command line, the function installs or uninstalls or - starts the service by calling into different routines. - -Environment: - - User mode - ---*/ - -#pragma region Includes -#include -#include -#include "ServiceBase.h" -#include "SampleService.h" -#pragma endregion - -// -// Settings of the service -// - -// -// Internal name of the service -// -#define SERVICE_NAME L"OsrUsbFx2UmUserSvc" - - -/*++ - -Routine Description: - - Entry point for the service. - -Arguments: - - Argc - The number of command line arguments - - Argv - The array of command line arguments - -Return Value: - - VOID - ---*/ -INT -wmain( - INT Argc, - WCHAR *Argv[] - ) -{ - CSampleService service(SERVICE_NAME); - - if (!CServiceBase::Run(service)) - { - wprintf(L"Service failed to run w/err 0x%08lx\n", GetLastError()); - } - - return 0; -} \ No newline at end of file diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.cpp new file mode 100644 index 000000000..318e0dd58 --- /dev/null +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.cpp @@ -0,0 +1,856 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + DeviceContext.cpp + +Abstract: + + Implements the functions to create/destroy device context by + registering/unregistering for device notifications. + +Environment: + + User mode + +--*/ + +#include "stdafx.h" + +extern HANDLE SvcStopRequestEvent; +extern HCMNOTIFICATION InterfaceNotificationHandle; +extern DEVICE_LIST_ENTRY DeviceList; +extern SRWLOCK DeviceListLock; + +// +// Keep track of running theads for unregistering device notifications +// +DWORD RunningUnregistrations = 0; +SRWLOCK RunningUnregistrationsLock = SRWLOCK_INIT; +CONDITION_VARIABLE UnregistrationComplete = CONDITION_VARIABLE_INIT; + +/*++ + +Routine Description: + + Setup device interface context by registering for device interface + notifications + +Arguments: + + NULL + +Return Value: + + A Win32 error code. + +--*/ +DWORD +SetupDeviceInterfaceContext( + VOID + ) +{ + DWORD Err = ERROR_SUCCESS; + CONFIGRET Cr = CR_SUCCESS; + PCWSTR DeviceInterface = NULL; + PWSTR DeviceInterfaceList = NULL; + DWORD DeviceInterfaceListSize = 0; + + // + // Register for device interface events to open and close the handle to + // the interface. + // + Err = RegisterInterfaceNotifications(&InterfaceNotificationHandle); + + if (Err != ERROR_SUCCESS) + { + goto cleanup; + } + + // + // The interface may already be present on the system. Retrieve a list of + // existing interfaces + // + do + { + Cr = CM_Get_Device_Interface_List_Size(&DeviceInterfaceListSize, + (LPGUID)&GUID_DEVINTERFACE_OSRUSBFX2, + NULL, + CM_GET_DEVICE_INTERFACE_LIST_PRESENT); + + if (Cr != CR_SUCCESS) + { + break; + } + + if (DeviceInterfaceList != NULL) + { + free(DeviceInterfaceList); + } + + DeviceInterfaceList = (PWSTR)malloc(DeviceInterfaceListSize * sizeof(WCHAR)); + + if (DeviceInterfaceList == NULL) + { + Cr = CR_OUT_OF_MEMORY; + break; + } + + Cr = CM_Get_Device_Interface_List((LPGUID)&GUID_DEVINTERFACE_OSRUSBFX2, + NULL, + DeviceInterfaceList, + DeviceInterfaceListSize, + CM_GET_DEVICE_INTERFACE_LIST_PRESENT); + } while (Cr == CR_BUFFER_SMALL); + + if (Cr != CR_SUCCESS) + { + Err = CM_MapCrToWin32Err(Cr, ERROR_INVALID_DATA); + goto cleanup; + } + + // + // Register for notifications on existing device interfaces + // + for (DeviceInterface = DeviceInterfaceList; + *DeviceInterface != L'\0'; + DeviceInterface += wcslen(DeviceInterface) + 1) + { + RegisterDeviceNotifications(DeviceInterface); + } + +cleanup: + + if (DeviceInterfaceList != NULL) + { + free(DeviceInterfaceList); + } + + return Err; +} + + +/*++ + +Routine Description: + + Clean up device interface context + +Arguments: + + NULL + +Return Value: + + NULL + +--*/ +VOID +CleanupDeviceInterfaceContext( + VOID + ) +{ + PDEVICE_CONTEXT Context = NULL; + BOOL NeedsUnregister = FALSE; + + // + // Unregister from the interface first, so that re-appearance of the + // interface does not cause us to register device events again. + // + if (InterfaceNotificationHandle != NULL) + { + CM_Unregister_Notification(InterfaceNotificationHandle); + InterfaceNotificationHandle = NULL; + } + + // + // Unregister notifications for device handles. + // + while (TRUE) + { + NeedsUnregister = FALSE; + + AcquireSRWLockShared(&DeviceListLock); + + if (IsDeviceListEmpty(&DeviceList)) + { + ReleaseSRWLockShared(&DeviceListLock); + break; + } + + // + // Get next device context + // + Context = CONTAINING_DEVICE_RECORD(DeviceList.Flink); + + // + // The device context can be unregistered either within notification + // callbacks or cleanup routines. Synchronize these operations to only + // unregister once. + // + EnterCriticalSection(&Context->ContextLock); + + if (!Context->Unregistered) + { + Context->Unregistered = TRUE; + NeedsUnregister = TRUE; + } + + LeaveCriticalSection(&Context->ContextLock); + + ReleaseSRWLockShared(&DeviceListLock); + + if (NeedsUnregister) + { + // + // Remove next device from device list + // + AcquireSRWLockExclusive(&DeviceListLock); + RemoveDeviceListEntry(DeviceList.Flink); + ReleaseSRWLockExclusive(&DeviceListLock); + + UnregisterDeviceNotifications(Context); + } + } + + // + // Wait for all other unregistrations for device handle that is not in + // device list. + // + AcquireSRWLockShared(&RunningUnregistrationsLock); + + while (RunningUnregistrations != 0) + { + SleepConditionVariableSRW(&UnregistrationComplete, + &RunningUnregistrationsLock, + INFINITE, + CONDITION_VARIABLE_LOCKMODE_SHARED); + } + + ReleaseSRWLockShared(&RunningUnregistrationsLock); +} + + +/*++ + +Routine Description: + + Handles a device query remove notification. + +Arguments: + + Context - The callback context + +Return Value: + + NULL + +--*/ +VOID +DeviceQueryRemoveAction( + _In_ PDEVICE_CONTEXT Context + ) +{ + if (Context->DeviceHandle != INVALID_HANDLE_VALUE) + { + // + // Close open handles to allow the device to be query removed + // + CloseHandle(Context->DeviceHandle); + + Context->DeviceHandle = INVALID_HANDLE_VALUE; + } +} + + +/*++ + +Routine Description: + + Handles a device query remove failed notification. + +Arguments: + + Context - The callback context + +Return Value: + + NULL + +--*/ +VOID +DeviceQueryRemoveFailedAction( + _In_ PDEVICE_CONTEXT Context + ) +{ + PWSTR DeviceInterfacePath = NULL; + BOOL NeedsUnregister = FALSE; + + // + // Keep a record of device symbolic link since the callback context will + // be freed up during unregistration + // + DeviceInterfacePath = Context->SymbolicLink; + Context->SymbolicLink = NULL; + + // + // The device context can be unregistered either within notification + // callbacks or cleanup routines. Synchronize these operations to only + // unregister once. + // + EnterCriticalSection(&Context->ContextLock); + + if (!Context->Unregistered) + { + Context->Unregistered = TRUE; + NeedsUnregister = TRUE; + } + + LeaveCriticalSection(&Context->ContextLock); + + // + // Remove device from device list if needed + // + if (NeedsUnregister) + { + AcquireSRWLockExclusive(&DeviceListLock); + RemoveDeviceListEntry(&Context->ListEntry); + ReleaseSRWLockExclusive(&DeviceListLock); + + // + // Unregister notifications for the old device handle from a deferred + // routine since CM_Unregister_Notification can not be called from a + // notification callback + // + AcquireSRWLockExclusive(&RunningUnregistrationsLock); + RunningUnregistrations++; + ReleaseSRWLockExclusive(&RunningUnregistrationsLock); + + QueueUserWorkItem(UnregisterDeviceNotificationsWorkerThread, + Context, + WT_EXECUTEDEFAULT); + } + + // + // Re-register for device notifications on a new device handle + // + RegisterDeviceNotifications(DeviceInterfacePath); + + // + // Free memory that the callback context used to point at but was not freed + // during unregistration + // + free(DeviceInterfacePath); +} + +/*++ + +Routine Description: + + Handles a device remove complete notification. + +Arguments: + + Context - The callback context + +Return Value: + + NULL + +--*/ +VOID +DeviceRemoveCompleteAction( + _In_ PDEVICE_CONTEXT Context + ) +{ + BOOL NeedsUnregister = FALSE; + + // + // The device context can be unregistered either within notification + // callbacks or cleanup routines. Synchronize these operations to only + // unregister once. + // + EnterCriticalSection(&Context->ContextLock); + + if (!Context->Unregistered) + { + Context->Unregistered = TRUE; + NeedsUnregister = TRUE; + } + + LeaveCriticalSection(&Context->ContextLock); + + // + // Remove device from device list if needed + // + if (NeedsUnregister) + { + AcquireSRWLockExclusive(&DeviceListLock); + RemoveDeviceListEntry(&Context->ListEntry); + ReleaseSRWLockExclusive(&DeviceListLock); + + // + // Unregister notifications for the old device handle from a deferred + // routine since CM_Unregister_Notification can not be called from a + // notification callback + // + AcquireSRWLockExclusive(&RunningUnregistrationsLock); + RunningUnregistrations++; + ReleaseSRWLockExclusive(&RunningUnregistrationsLock); + + QueueUserWorkItem(UnregisterDeviceNotificationsWorkerThread, + Context, + WT_EXECUTEDEFAULT); + } +} + +/*++ + +Routine Description: + + Handles device notifications. + +Arguments: + + hNotify - The notification that spurred this callback + + hContext - The callback context + + Action - The type of callback + + EventData - Additional information about this callback + + EventDataSize - The size of EventData + +Return Value: + + A Win32 error code. + +--*/ +DWORD +WINAPI +DeviceCallback( + _In_ HCMNOTIFICATION hNotify, + _In_ PVOID hContext, + _In_ CM_NOTIFY_ACTION Action, + _In_ PCM_NOTIFY_EVENT_DATA EventData, + _In_ DWORD EventDataSize + ) +{ + PDEVICE_CONTEXT Context = (PDEVICE_CONTEXT)hContext; + + UNREFERENCED_PARAMETER(EventData); + UNREFERENCED_PARAMETER(EventDataSize); + + // + // In case this callback fires before the registration call returns, make + // sure the notification handle is properly set + // + Context->DeviceNotificationHandle = hNotify; + + switch (Action) + { + case CM_NOTIFY_ACTION_DEVICEQUERYREMOVE: + DeviceQueryRemoveAction(Context); + break; + + case CM_NOTIFY_ACTION_DEVICEQUERYREMOVEFAILED: + DeviceQueryRemoveFailedAction(Context); + break; + + case CM_NOTIFY_ACTION_DEVICEREMOVEPENDING: + case CM_NOTIFY_ACTION_DEVICEREMOVECOMPLETE: + DeviceRemoveCompleteAction(Context); + break; + + default: + break; + } + + return ERROR_SUCCESS; +} + + +/*++ + +Routine Description: + + Register for device notifications. + +Arguments: + + DeviceInterfacePath - The symbolic link path of the device interface + +Return Value: + + A Win32 error code. + +--*/ +DWORD +RegisterDeviceNotifications( + _In_ PCWSTR DeviceInterfacePath + ) +{ + DWORD Err = ERROR_SUCCESS; + CONFIGRET Cr = CR_SUCCESS; + PDEVICE_CONTEXT Context = NULL; + PDEVICE_LIST_ENTRY Link = NULL; + DWORD BufferSize = 0; + CM_NOTIFY_FILTER NotifyFilter = {0}; + + // + // Check whether the device interface has already been registered for device + // handle notifications since it can be done either in interface arrival + // callback routine or initial device interface setup routine + // + AcquireSRWLockExclusive(&DeviceListLock); + + for (Link = DeviceList.Flink; Link != &DeviceList; Link = Link->Flink) + { + Context = CONTAINING_DEVICE_RECORD(Link); + + if (_wcsicmp(DeviceInterfacePath, Context->SymbolicLink) == 0) + { + break; + } + } + + if (Link != &DeviceList) + { + Err = ERROR_SUCCESS; + goto cleanup; + } + + // + // Create a new device context + // + Context = (PDEVICE_CONTEXT)malloc(sizeof(DEVICE_CONTEXT)); + + if (Context == NULL) + { + Err = ERROR_OUTOFMEMORY; + goto cleanup; + } + + // + // Initialize device context + // + ZeroMemory(Context, sizeof(DEVICE_CONTEXT)); + Context->DeviceHandle = INVALID_HANDLE_VALUE; + InitializeCriticalSection(&Context->ContextLock); + + // + // Fill out the context and register device handle notifications + // + BufferSize = (DWORD)wcslen(DeviceInterfacePath) + 1; + Context->SymbolicLink = (PWSTR)malloc(BufferSize * sizeof(WCHAR)); + + if ((Context->SymbolicLink == NULL) || + (FAILED(StringCchCopy(Context->SymbolicLink, + BufferSize, + DeviceInterfacePath)))) + { + Err = ERROR_OUTOFMEMORY; + goto cleanup; + } + + Context->DeviceHandle = CreateFile(Context->SymbolicLink, + GENERIC_WRITE | GENERIC_READ, + FILE_SHARE_WRITE | FILE_SHARE_READ, + NULL, // default security + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, + NULL); + + if (Context->DeviceHandle == INVALID_HANDLE_VALUE) + { + Err = GetLastError(); + goto cleanup; + } + + NotifyFilter.cbSize = sizeof(NotifyFilter); + NotifyFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE; + NotifyFilter.u.DeviceHandle.hTarget = Context->DeviceHandle; + + Cr = CM_Register_Notification(&NotifyFilter, + (PVOID)Context, + (PCM_NOTIFY_CALLBACK)DeviceCallback, + &Context->DeviceNotificationHandle); + + if (Cr != CR_SUCCESS) + { + Err = CM_MapCrToWin32Err(Cr, ERROR_INVALID_DATA); + goto cleanup; + } + + // + // Add the device entry to device list + // + InsertTailDeviceListEntry(&DeviceList, &Context->ListEntry); + Context = NULL; + +cleanup: + + ReleaseSRWLockExclusive(&DeviceListLock); + + // + // Clean up device context if an error occurred. + // + if (Context != NULL) + { + if (Context->SymbolicLink != NULL) + { + free(Context->SymbolicLink); + } + + if (Context->DeviceHandle != INVALID_HANDLE_VALUE) + { + CloseHandle(Context->DeviceHandle); + } + + free(Context); + } + + return Err; +} + + +VOID +UnregisterDeviceNotifications( + _Inout_ PDEVICE_CONTEXT Context + ) +{ + if (Context->DeviceNotificationHandle != NULL) + { + CM_Unregister_Notification(Context->DeviceNotificationHandle); + } + + if (Context->DeviceHandle != INVALID_HANDLE_VALUE) + { + CloseHandle(Context->DeviceHandle); + } + + if (Context->SymbolicLink != NULL) + { + free(Context->SymbolicLink); + } + + DeleteCriticalSection(&Context->ContextLock); + + free(Context); +} + + +/*++ + +Routine Description: + + This worker thread avoids a deadlock when unregistering device notifications. + Rather than calling CM_Unregister_Notification from the callback, the + callback gives that work to a separate thread to avoid deadlock. + +Arguments: + + lpThreadParameter - The thread data passed to the function + +Return Value: + + Zero + +--*/ +DWORD +WINAPI +UnregisterDeviceNotificationsWorkerThread( + _In_ PVOID lpThreadParameter + ) +{ + PDEVICE_CONTEXT Context = (PDEVICE_CONTEXT)lpThreadParameter; + + UnregisterDeviceNotifications(Context); + + // + // Decrease running unregistrations + // + AcquireSRWLockExclusive(&RunningUnregistrationsLock); + RunningUnregistrations--; + ReleaseSRWLockExclusive(&RunningUnregistrationsLock); + + WakeAllConditionVariable(&UnregistrationComplete); + + return 0; +} + + +/*++ + +Routine Description: + + Handles an interface arrival notification. + +Arguments: + + hNotify - The notification that fired the callback + + hContext - The callback context + + Action - The type of notification + + EventData - Additional information about the callback + + EventDataSize - The size of EventData + +Return Value: + + Notification callback should return ERROR_SUCCESS. + +--*/ +DWORD +WINAPI +InterfaceCallback( + _In_ HCMNOTIFICATION hNotify, + _In_ PVOID hContext, + _In_ CM_NOTIFY_ACTION Action, + _In_ PCM_NOTIFY_EVENT_DATA EventData, + _In_ DWORD EventDataSize + ) +{ + PDEVICE_CONTEXT Context = NULL; + PDEVICE_LIST_ENTRY Link = NULL; + BOOL NeedsUnregister = FALSE; + + UNREFERENCED_PARAMETER(hNotify); + UNREFERENCED_PARAMETER(hContext); + UNREFERENCED_PARAMETER(EventDataSize); + + switch (Action) + { + case CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL: + // + // Register for device notifications + // + RegisterDeviceNotifications(EventData->u.DeviceInterface.SymbolicLink); + break; + + case CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL: + // + // The device may still be running in the case where the driver disables + // its interfaces. Find whether it is still on the device list and clean + // it up. + // + AcquireSRWLockShared(&DeviceListLock); + + for (Link = DeviceList.Flink; Link != &DeviceList; Link = Link->Flink) + { + Context = CONTAINING_DEVICE_RECORD(Link); + + if (_wcsicmp(EventData->u.DeviceInterface.SymbolicLink, + Context->SymbolicLink) == 0) + { + // + // The device context can be unregistered either within + // notification callbacks or cleanup routines. Synchronize these + // operations to only unregister once. + // + EnterCriticalSection(&Context->ContextLock); + + if (!Context->Unregistered) + { + Context->Unregistered = TRUE; + NeedsUnregister = TRUE; + } + + LeaveCriticalSection(&Context->ContextLock); + + break; + } + } + + ReleaseSRWLockShared(&DeviceListLock); + + if (NeedsUnregister) + { + // + // Remove the device from device list + // + AcquireSRWLockExclusive(&DeviceListLock); + RemoveDeviceListEntry(&Context->ListEntry); + ReleaseSRWLockExclusive(&DeviceListLock); + + UnregisterDeviceNotifications(Context); + } + + // + // Notify service to stop if this is the last device interface + // + AcquireSRWLockShared(&DeviceListLock); + + if (IsDeviceListEmpty(&DeviceList)) + { + SetEvent(SvcStopRequestEvent); + } + + ReleaseSRWLockShared(&DeviceListLock); + break; + + default: + break; + } + + return ERROR_SUCCESS; +} + + +/*++ + +Routine Description: + + Registers the service for interface notifications + +Arguments: + + pInterfaceNotificationHandle - Pointer to receive the HCMNOTIFICATION handle + +Return Value: + + A Win32 error code. + +--*/ +DWORD +RegisterInterfaceNotifications( + _Out_ PHCMNOTIFICATION pInterfaceNotificationHandle + ) +{ + DWORD Err = ERROR_SUCCESS; + CONFIGRET Cr = CR_SUCCESS; + CM_NOTIFY_FILTER NotifyFilter = {0}; + + NotifyFilter.cbSize = sizeof(NotifyFilter); + NotifyFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE; + NotifyFilter.u.DeviceInterface.ClassGuid = GUID_DEVINTERFACE_OSRUSBFX2; + + // + // Register for device interface events to open and close the handle to + // the interface. + // + Cr = CM_Register_Notification(&NotifyFilter, + NULL, + (PCM_NOTIFY_CALLBACK)InterfaceCallback, + pInterfaceNotificationHandle); + + if (Cr != CR_SUCCESS) + { + Err = CM_MapCrToWin32Err(Cr, ERROR_INVALID_DATA); + goto cleanup; + } + +cleanup: + + return Err; +} diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.h new file mode 100644 index 000000000..4d7449895 --- /dev/null +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceContext.h @@ -0,0 +1,155 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +--*/ + +#pragma once + +// +// Device list +// +typedef struct _DEVICE_LIST_ENTRY { + struct _DEVICE_LIST_ENTRY *Flink; + struct _DEVICE_LIST_ENTRY *Blink; +} DEVICE_LIST_ENTRY, *PDEVICE_LIST_ENTRY; + +FORCEINLINE +VOID +InitializeDeviceListHead( + _Out_ PDEVICE_LIST_ENTRY Head + ) +{ + Head->Blink = Head->Flink = Head; +} + +FORCEINLINE +BOOL +IsDeviceListEmpty( + _In_ const PDEVICE_LIST_ENTRY ListHead + ) + +{ + return (ListHead->Flink == ListHead); +} + +FORCEINLINE +VOID +RemoveDeviceListEntry( + _In_ PDEVICE_LIST_ENTRY Entry + ) +{ + PDEVICE_LIST_ENTRY Prev = Entry->Blink; + PDEVICE_LIST_ENTRY Next = Entry->Flink; + + Prev->Flink = Next; + Next->Blink = Prev; +} + +FORCEINLINE +VOID +InsertTailDeviceListEntry( + _Inout_ PDEVICE_LIST_ENTRY Head, + _Inout_ PDEVICE_LIST_ENTRY Entry + ) +{ + PDEVICE_LIST_ENTRY Tail = Head->Blink; + + Tail->Flink = Entry; + Entry->Blink = Tail; + Entry->Flink = Head; + Head->Blink = Entry; +} + +// +// Context for device handle +// +typedef struct _DEVICE_CONTEXT { + PWSTR SymbolicLink; + HANDLE DeviceHandle; + HCMNOTIFICATION DeviceNotificationHandle; + BOOL Unregistered; + CRITICAL_SECTION ContextLock; + DEVICE_LIST_ENTRY ListEntry; +} DEVICE_CONTEXT, *PDEVICE_CONTEXT; + +#define CONTAINING_DEVICE_RECORD(address) ((PDEVICE_CONTEXT)( \ + (PCHAR)(address) - \ + (ULONG_PTR)(&((PDEVICE_CONTEXT)0)->ListEntry))) + +// +// Device interface context +// +DWORD +SetupDeviceInterfaceContext( + VOID + ); + +VOID +CleanupDeviceInterfaceContext( + VOID + ); + +// +// Device notifications related +// +VOID +DeviceQueryRemoveAction( + _In_ PDEVICE_CONTEXT Context + ); + +VOID +DeviceQueryRemoveFailedAction( + _In_ PDEVICE_CONTEXT Context + ); + +VOID +DeviceRemoveCompleteAction( + _In_ PDEVICE_CONTEXT Context + ); + +DWORD +WINAPI +DeviceCallback( + _In_ HCMNOTIFICATION hNotify, + _In_ PVOID hContext, + _In_ CM_NOTIFY_ACTION Action, + _In_ PCM_NOTIFY_EVENT_DATA EventData, + _In_ DWORD EventDataSize + ); + +DWORD +RegisterDeviceNotifications( + _In_ PCWSTR DeviceInterfacePath + ); + +VOID +UnregisterDeviceNotifications( + _Inout_ PDEVICE_CONTEXT Context + ); + +DWORD +WINAPI +InterfaceCallback( + _In_ HCMNOTIFICATION hNotify, + _In_ PVOID hContext, + _In_ CM_NOTIFY_ACTION Action, + _In_ PCM_NOTIFY_EVENT_DATA EventData, + _In_ DWORD EventDataSize + ); + +DWORD +RegisterInterfaceNotifications( + _Out_ PHCMNOTIFICATION pInterfaceNotificationHandle + ); + +DWORD +WINAPI +UnregisterDeviceNotificationsWorkerThread( + _In_ PVOID lpThreadParameter + ); diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.cpp new file mode 100644 index 000000000..ced895ccc --- /dev/null +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.cpp @@ -0,0 +1,192 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + DeviceControl.cpp + +Abstract: + + Implements the functions to control the OSR USB FX2 device. + +Environment: + + User mode + +--*/ + +#include "stdafx.h" + +// +// Keep track of where the OSRFX2 device's bar graph currently is. +// +INT CurrentBar; +BAR_GRAPH_STATE BarGraphState; + +/*++ + +Routine Description: + + Initialize global variables for OSRFX2 device. + +Arguments: + + VOID + +Return Value: + + VOID + +--*/ +VOID +OsrFx2InitializeDevice( + VOID + ) +{ + CurrentBar = 0; +} + + +/*++ + +Routine Description: + + Turns off all of the bar graph lights on the OSR USB FX2 device. + +Arguments: + + Context - The callback context + +Return Value: + + VOID + +--*/ +DWORD +OsrFx2ClearAllBars( + _In_ PDEVICE_CONTEXT Context + ) +{ + DWORD Err = ERROR_SUCCESS; + ULONG BytesReturned; + + BarGraphState.BarsAsUChar = 0; + + if (!DeviceIoControl(Context->DeviceHandle, + IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY, + &BarGraphState, // Pointer to InBuffer + sizeof(BAR_GRAPH_STATE), // Length of InBuffer + NULL, // Pointer to OutBuffer + 0, // Length of OutBuffer + &BytesReturned, // BytesReturned + 0)) // Pointer to Overlapped structure + { + Err = GetLastError(); + goto cleanup; + } + +cleanup: + + return Err; +} + + +/*++ + +Routine Description: + + Lights the next bar on the OSR USB FX2 device. + +Arguments: + + Context - The callback context + +Return Value: + + VOID + +--*/ +DWORD +OsrFx2LightNextBar( + _In_ PDEVICE_CONTEXT Context + ) +{ + DWORD Err = ERROR_SUCCESS; + ULONG BytesReturned; + + // + // Normalize to 0-7 + // + CurrentBar += 1; + + if (CurrentBar > 7) + { + CurrentBar = 0; + } + + BarGraphState.BarsAsUChar = 1 << (UCHAR)CurrentBar; + + if (!DeviceIoControl(Context->DeviceHandle, + IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY, + &BarGraphState, // Pointer to InBuffer + sizeof(BAR_GRAPH_STATE), // Length of InBuffer + NULL, // Pointer to OutBuffer + 0, // Length of OutBuffer + &BytesReturned, // BytesReturned + 0)) // Pointer to Overlapped structure + { + Err = GetLastError(); + goto cleanup; + } + +cleanup: + + return Err; +} + +/*++ + +Routine Description: + + Lights the next bar on the OSRFX2 device. + +Arguments: + + Context - The device context + +Return Value: + + A Win32 error code. + +--*/ +DWORD +OsrFx2ControlDevice( + _In_ PDEVICE_CONTEXT Context + ) +{ + DWORD Err = ERROR_SUCCESS; + + Err = OsrFx2ClearAllBars(Context); + + if (Err != ERROR_SUCCESS) + { + goto cleanup; + } + + Err = OsrFx2LightNextBar(Context); + + if (Err != ERROR_SUCCESS) + { + goto cleanup; + } + +cleanup: + + return Err; +} diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.h new file mode 100644 index 000000000..235e64bab --- /dev/null +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/DeviceControl.h @@ -0,0 +1,144 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +--*/ + +#pragma once +#pragma warning(disable : 4201) // disable nameless struct/union warning + +// +// {573E8C73-0CB4-4471-A1BF-FAB26C31D384} +// +DEFINE_GUID(GUID_DEVINTERFACE_OSRUSBFX2, + 0x573e8c73, 0xcb4, 0x4471, 0xa1, 0xbf, 0xfa, 0xb2, 0x6c, 0x31, 0xd3, 0x84); + +// +// Define the structures that will be used by the IOCTL interface to the driver +// + +// BAR_GRAPH_STATE is a bit field structure with each bit corresponding to one +// of the bar graph on the OSRFX2 Development Board +// +typedef struct _BAR_GRAPH_STATE { + + union { + + struct { + // + // Individual bars starting from the top of the stack of bars + // + // NOTE: There are actually 10 bars, but the very top two do not + // light and are not counted here + // + UCHAR Bar1 : 1; + UCHAR Bar2 : 1; + UCHAR Bar3 : 1; + UCHAR Bar4 : 1; + UCHAR Bar5 : 1; + UCHAR Bar6 : 1; + UCHAR Bar7 : 1; + UCHAR Bar8 : 1; + }; + + // + // The state of all the bar graph as a single + // UCHAR + // + UCHAR BarsAsUChar; + }; + +} BAR_GRAPH_STATE, *PBAR_GRAPH_STATE; + +// +// SWITCH_STATE is a bit field structure with each bit corresponding to one of +// the switches on the OSRFX2 Development Board +// +typedef struct _SWITCH_STATE { + + union { + struct { + // + // Individual switches starting from the left of the set of switches + // + UCHAR Switch1 : 1; + UCHAR Switch2 : 1; + UCHAR Switch3 : 1; + UCHAR Switch4 : 1; + UCHAR Switch5 : 1; + UCHAR Switch6 : 1; + UCHAR Switch7 : 1; + UCHAR Switch8 : 1; + }; + + // + // The state of all the switches as a single + // UCHAR + // + UCHAR SwitchesAsUChar; + }; + +} SWITCH_STATE, *PSWITCH_STATE; + +DWORD +OsrFx2ControlDevice( + _In_ PDEVICE_CONTEXT Context + ); + +VOID +OsrFx2InitializeDevice( + VOID + ); + +#define IOCTL_INDEX 0x800 +#define FILE_DEVICE_OSRUSBFX2 65500U + +#define IOCTL_OSRUSBFX2_GET_CONFIG_DESCRIPTOR CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ + IOCTL_INDEX, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS) + +#define IOCTL_OSRUSBFX2_RESET_DEVICE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ + IOCTL_INDEX + 1, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +#define IOCTL_OSRUSBFX2_REENUMERATE_DEVICE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ + IOCTL_INDEX + 3, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +#define IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ + IOCTL_INDEX + 4, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS) + +#define IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ + IOCTL_INDEX + 5, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +#define IOCTL_OSRUSBFX2_READ_SWITCHES CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ + IOCTL_INDEX + 6, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS) + +#define IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ + IOCTL_INDEX + 7, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS) + +#define IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ + IOCTL_INDEX + 8, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +#define IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE CTL_CODE(FILE_DEVICE_OSRUSBFX2,\ + IOCTL_INDEX + 9, \ + METHOD_OUT_DIRECT, \ + FILE_READ_ACCESS) diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.cpp deleted file mode 100644 index a02ac24af..000000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.cpp +++ /dev/null @@ -1,1217 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - Main.cpp - -Abstract: - - Implements the functions to control the OSR USB FX2 device. - -Environment: - - User mode - ---*/ - -#include "Main.h" -#include "Utils.h" - -// -// Keep track of where the OSRFX2 device's bar graph currently is. -// -INT CurrentBar; -BAR_GRAPH_STATE BarGraphState; - -/*++ - -Routine Description: - - Sets the variables in this service to their default values. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -SetVariables() -{ - CurrentBar = 0; -} - - -/*++ - -Routine Description: - - Retrieves the device path of a given interface. - -Arguments: - - InterfaceGuid - The GUID of the interface to search for - - DevicePath - The resulting device path - - DevicePathLength - The length of DevicePath - -Return Value: - - TRUE if the function succeeded and FALSE otherwise. Errors - are logged in the Application event log. - ---*/ -_Success_(return) -BOOL -GetDevicePath( - _In_ LPGUID InterfaceGuid, - _Out_writes_z_(DevicePathLength) PWCHAR DevicePath, - _In_ size_t DevicePathLength - ) -{ - HRESULT hr = E_FAIL; - CONFIGRET cr = CR_SUCCESS; - PWSTR DeviceInterfaceList = NULL; - ULONG DeviceInterfaceListLength = 0; - PWSTR NextInterface; - - // - // Determine if there are any interfaces that match the OSRFX2 device. - // - cr = CM_Get_Device_Interface_List_Size(&DeviceInterfaceListLength, - InterfaceGuid, - NULL, - CM_GET_DEVICE_INTERFACE_LIST_PRESENT); - - if (cr != CR_SUCCESS) - { - WriteToErrorLog(L"CM_Get_DeviceInterface_List_Size", - CM_MapCrToWin32Err(cr, ERROR_FILE_NOT_FOUND)); - goto cleanup; - } - - if (DeviceInterfaceListLength < 1) - { - WriteToErrorLog(L"CM_Get_DeviceInterface_List_Size", - CM_MapCrToWin32Err(cr, ERROR_EMPTY)); - goto cleanup; - } - - DeviceInterfaceList = (PWSTR)malloc(DeviceInterfaceListLength * sizeof(WCHAR)); - - if (DeviceInterfaceList == NULL) - { - WriteToEventLog(L"Failed to allocate memory for the device interface list", - TRACE_LEVEL_ERROR); - goto cleanup; - } - - cr = CM_Get_Device_Interface_List(InterfaceGuid, - NULL, - DeviceInterfaceList, - DeviceInterfaceListLength, - CM_GET_DEVICE_INTERFACE_LIST_PRESENT); - - if (cr != CR_SUCCESS) - { - WriteToErrorLog(L"CM_Get_Device_Interface_List", - CM_MapCrToWin32Err(cr, ERROR_FILE_NOT_FOUND)); - goto cleanup; - } - - if (*DeviceInterfaceList == UNICODE_NULL) - { - WriteToEventLog(L"CM_Get_Device_Interface_List returned an empty list", - TRACE_LEVEL_ERROR); - } - - // - // This sample only expects one interface for the OSRFX2 device. For other - // devices, though, it maybe necessary to sift through the interfaces - // from CM_Get_Device_Interface_List in order to find the correct device. - // - NextInterface = DeviceInterfaceList + wcslen(DeviceInterfaceList) + 1; - - if (*NextInterface != UNICODE_NULL) - { - WriteToEventLog(L"More than one device interface instance found. " - "Selecting first matching device.", - TRACE_LEVEL_WARNING); - } - - hr = StringCchCopy(DevicePath, DevicePathLength, DeviceInterfaceList); - - if (FAILED(hr)) - { - WriteToErrorLog(L"StringCchCopy", HRESULT_CODE(hr)); - goto cleanup; - } - -cleanup: - - if (DeviceInterfaceList != NULL) - { - free(DeviceInterfaceList); - } - - return (cr == CR_SUCCESS); -} - - -/*++ - -Routine Description: - - Opens up the OSR USB FX2 device handle. - -Arguments: - - Synchronous - Whether or not this device should be opened for syncrhonous - access - -Return Value: - - The handle to the OSR USB FX2 device. - ---*/ -_Check_return_ -_Ret_notnull_ -_Success_(return != INVALID_HANDLE_VALUE) -HANDLE -OpenDevice( - _In_ BOOL Synchronous - ) -{ - HANDLE DeviceHandle = INVALID_HANDLE_VALUE; - WCHAR DeviceName[MAX_DEVPATH_LENGTH]; - - if (!GetDevicePath((LPGUID)&GUID_DEVINTERFACE_OSRUSBFX2, - DeviceName, - sizeof(DeviceName) / sizeof(DeviceName[0]))) - { - goto cleanup; - } - - // - // Open a handle to the interface. - // - if (Synchronous) - { - DeviceHandle = CreateFile(DeviceName, - GENERIC_WRITE | GENERIC_READ, - FILE_SHARE_WRITE | FILE_SHARE_READ, - NULL, // default security - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - } - else - { - DeviceHandle = CreateFile(DeviceName, - GENERIC_WRITE | GENERIC_READ, - FILE_SHARE_WRITE | FILE_SHARE_READ, - NULL, // default security - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, - NULL); - } - - if (DeviceHandle == INVALID_HANDLE_VALUE) - { - WriteToErrorLog(L"CreateFile", GetLastError()); - } - else - { - WriteToEventLog(L"Opened Device Successfully", TRACE_LEVEL_INFORMATION); - } - -cleanup: - - return DeviceHandle; -} - - -/*++ - -Routine Description: - - Handles an interface arrival notification. - -Arguments: - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -InterfaceArrivalAction( - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - - // - // Now that the interface has arrived, open a handle to it, and then - // register that handle for device events. - // - EnterCriticalSection(&Context->Lock); - - if (Context->DeviceInterfaceHandle != INVALID_HANDLE_VALUE) - { - // - // The handle was already retrieved. - // - Err = ERROR_SUCCESS; - goto cleanup; - } - - Context->DeviceInterfaceHandle = OpenDevice(FALSE); - - if (Context->DeviceInterfaceHandle == INVALID_HANDLE_VALUE) - { - Err = GetLastError(); - WriteToErrorLog(L"Could not open device interface", Err); - goto cleanup; - } - - Err = RegisterDeviceNotifications(Context); - - if (Err != ERROR_SUCCESS) - { - WriteToErrorLog(L"Could not register device notifications", Err); - goto cleanup; - } - -cleanup: - - LeaveCriticalSection(&Context->Lock); - - return Err; -} - - -/*++ - -Routine Description: - - Handles an interface arrival notification. - -Arguments: - - hNotify - The notification that fired the callback - - hContext - The callback context - - Action - The type of notification - - EventData - Additional information about the callback - - EventDataSize - The size of EventData - -Return Value: - - A Win32 error code. - ---*/ -DWORD -InterfaceCallback( - _In_ HCMNOTIFICATION hNotify, - _In_ PVOID hContext, - _In_ CM_NOTIFY_ACTION Action, - _In_ PCM_NOTIFY_EVENT_DATA EventData, - _In_ DWORD EventDataSize - ) -{ - DWORD Err = ERROR_SUCCESS; - PDEVICE_CONTEXT Context = (PDEVICE_CONTEXT)hContext; - - // - // Validate Context. - // - if (Context == NULL) - { - goto cleanup; - } - - if (Action == CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL) - { - Err = InterfaceArrivalAction(Context); - } - -cleanup: - - return Err; -} - - -/*++ - -Routine Description: - - Registers the service for notifications using the notification handle in - Context. - -Arguments: - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -RegisterInterfaceNotifications( - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - CONFIGRET cr; - CM_NOTIFY_FILTER NotifyFilter = {0}; - - if (Context == NULL) - { - goto cleanup; - } - - ZeroMemory(&NotifyFilter, sizeof(NotifyFilter)); - NotifyFilter.cbSize = sizeof(NotifyFilter); - NotifyFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE; - NotifyFilter.u.DeviceInterface.ClassGuid = GUID_DEVINTERFACE_OSRUSBFX2; - - cr = CM_Register_Notification(&NotifyFilter, - (PVOID)Context, - (PCM_NOTIFY_CALLBACK)InterfaceCallback, - &Context->InterfaceNotificationHandle); - - if (cr != CR_SUCCESS) - { - Err = CM_MapCrToWin32Err(cr, ERROR_INVALID_DATA); - WriteToErrorLog(L"CM_Register_Notification", Err); - goto cleanup; - } - -cleanup: - - return Err; -} - - -/*++ - -Routine Description: - - Unregister for interface notifications. Note, this routine deadlocks - when called from an interface callback. - -Arguments: - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -UnregisterInterfaceNotifications( - _In_ PDEVICE_CONTEXT Context - ) -{ - CONFIGRET cr; - - if (Context->InterfaceNotificationHandle != NULL) - { - cr = CM_Unregister_Notification(Context->InterfaceNotificationHandle); - - Context->InterfaceNotificationHandle = NULL; - } - - return CM_MapCrToWin32Err(cr, ERROR_INVALID_DATA); -} - - -/*++ - -Routine Description: - - Callback for when a device is being query removed. - -Arguments: - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -DeviceQueryRemoveAction( - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - - EnterCriticalSection(&Context->Lock); - - if (Context->DeviceInterfaceHandle != INVALID_HANDLE_VALUE) - { - // - // Close open handles to allow the device to exit - // - CloseHandle(Context->DeviceInterfaceHandle); - - Context->DeviceInterfaceHandle = INVALID_HANDLE_VALUE; - } - - LeaveCriticalSection(&Context->Lock); - - return Err; -} - - -/*++ - -Routine Description: - - This callback avoids a deadlock when unregistering device notifications. - Rather than calling CM_Unregister_Notification from the callback, the - callback gives that work to a separate thread to avoid deadlock. - -Arguments: - - Instance - The thread's callback instance - - hContext - The callback context - - pWork - The thread handle - -Return Value: - - VOID - ---*/ -VOID -CALLBACK -UnregisterWorkerThreadCallback( - _Inout_ PTP_CALLBACK_INSTANCE Instance, - _Inout_opt_ PVOID hContext, - _Inout_ PTP_WORK pWork - ) -{ - PDEVICE_CONTEXT Context = (PDEVICE_CONTEXT)hContext; - - EnterCriticalSection(&Context->Lock); - - UnregisterDeviceNotifications(Context); - - // - // Close the device handle. - // - if (Context->DeviceInterfaceHandle != INVALID_HANDLE_VALUE) - { - CloseHandle(Context->DeviceInterfaceHandle); - - Context->DeviceInterfaceHandle = INVALID_HANDLE_VALUE; - } - - LeaveCriticalSection(&Context->Lock); -} - - -/*++ - -Routine Description: - - Handles a device query remove failed notification. - -Arguments: - - hNotify - The notification that spurred this callback - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -DeviceQueryRemoveFailedAction( - _In_ HCMNOTIFICATION hNotify, - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - - EnterCriticalSection(&Context->Lock); - - // - // In case this callback fires before the registration call returns, make - // sure the notification handle is properly set. - // - Context->InterfaceNotificationHandle = hNotify; - - // - // Unregister the device callback, and then close the handle - // - if (!Context->Unregister) - { - Context->Unregister = TRUE; - SubmitThreadpoolWork(Context->Work); - } - - LeaveCriticalSection(&Context->Lock); - - // - // Wait for the callback and then re-register the device - // - WaitForThreadpoolWorkCallbacks(Context->Work, FALSE); - - EnterCriticalSection(&Context->Lock); - - if (Context->DeviceInterfaceHandle == INVALID_HANDLE_VALUE) - { - Context->DeviceInterfaceHandle = OpenDevice(FALSE); - } - - if (Context->DeviceInterfaceHandle != INVALID_HANDLE_VALUE) - { - RegisterDeviceNotifications(Context); - } - - LeaveCriticalSection(&Context->Lock); - - return Err; -} - - -/*++ - -Routine Description: - - Handles a device remove pending notification. - -Arguments: - - hNotify - The notification that spurred this callback - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -DeviceRemovePendingAction( - _In_ HCMNOTIFICATION hNotify, - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - - EnterCriticalSection(&Context->Lock); - - // - // In case this callback fires before the registration call returns, make - // sure the notification handle is properly set. - // - Context->InterfaceNotificationHandle = hNotify; - - // - // Unregister the device callback, and then close the handle - // - if (!Context->Unregister) - { - Context->Unregister = TRUE; - SubmitThreadpoolWork(Context->Work); - } - - LeaveCriticalSection(&Context->Lock); - - return Err; -} - - -/*++ - -Routine Description: - - Handles a device remove complete notification. - -Arguments: - - hNotify - The notification that spurred this callback - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -DeviceRemoveCompleteAction( - _In_ HCMNOTIFICATION hNotify, - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - - EnterCriticalSection(&Context->Lock); - - // - // In case this callback fires before the registration call returns, make - // sure the notification handle is properly set. - // - Context->InterfaceNotificationHandle = hNotify; - - // - // Unregister the device callback, and then close the handle - // - if (!Context->Unregister) - { - Context->Unregister = TRUE; - SubmitThreadpoolWork(Context->Work); - } - - LeaveCriticalSection(&Context->Lock); - - return Err; -} - - -/*++ - -Routine Description: - - Handles device notifications. - -Arguments: - - hNotify - The notification that spurred this callback - - hContext - The callback context - - Action - The type of callback - - EventData - Additional information about this callback - - EventDataSize - The size of EventData - -Return Value: - - A Win32 error code. - ---*/ -DWORD -DeviceCallback( - _In_ HCMNOTIFICATION hNotify, - _In_ PVOID hContext, - _In_ CM_NOTIFY_ACTION Action, - _In_ PCM_NOTIFY_EVENT_DATA EventData, - _In_ DWORD EventDataSize - ) -{ - DWORD Err = ERROR_SUCCESS; - PDEVICE_CONTEXT Context = (PDEVICE_CONTEXT)hContext; - - // - // Validate Context. - // - if (Context == NULL) - { - goto cleanup; - } - - switch (Action) - { - case CM_NOTIFY_ACTION_DEVICEQUERYREMOVE: - DeviceQueryRemoveAction(Context); - break; - - case CM_NOTIFY_ACTION_DEVICEQUERYREMOVEFAILED: - DeviceQueryRemoveFailedAction(hNotify, Context); - break; - - case CM_NOTIFY_ACTION_DEVICEREMOVEPENDING: - DeviceRemovePendingAction(hNotify, Context); - break; - - case CM_NOTIFY_ACTION_DEVICEREMOVECOMPLETE: - DeviceRemoveCompleteAction(hNotify, Context); - break; - } - -cleanup: - - return Err; -} - - -/*++ - -Routine Description: - - Register for device notifications. - -Arguments: - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -RegisterDeviceNotifications( - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - CONFIGRET cr; - CM_NOTIFY_FILTER NotifyFilter = {0}; - - NotifyFilter.cbSize = sizeof(NotifyFilter); - NotifyFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEHANDLE; - NotifyFilter.u.DeviceHandle.hTarget = Context->DeviceInterfaceHandle; - - cr = CM_Register_Notification(&NotifyFilter, - (PVOID)Context, - (PCM_NOTIFY_CALLBACK)DeviceCallback, - &Context->DeviceNotificationHandle); - - if (cr != CR_SUCCESS) - { - Err = CM_MapCrToWin32Err(cr, ERROR_INVALID_DATA); - WriteToEventLog(L"Could not register for notifications", TRACE_LEVEL_WARNING); - goto cleanup; - } - - Context->Unregister = FALSE; - -cleanup: - - return Err; -} - - -/*++ - -Routine Description: - - Unregister for device notifications. - -Arguments: - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -UnregisterDeviceNotifications( - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - CONFIGRET cr; - - if (Context->DeviceNotificationHandle != NULL) - { - cr = CM_Unregister_Notification(Context->DeviceNotificationHandle); - - if (cr != CR_SUCCESS) - { - Err = CM_MapCrToWin32Err(cr, ERROR_INVALID_DATA); - WriteToEventLog(L"Could not unregister notifications", TRACE_LEVEL_WARNING); - } - - Context->DeviceNotificationHandle = NULL; - } - - return Err; -} - - -/*++ - -Routine Description: - - Initialize the given PDEVICE_CONTEXT. - -Arguments: - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -InitializeContext( - _Out_ PDEVICE_CONTEXT *Context - ) -{ - DWORD Err = ERROR_SUCCESS; - BOOL LockInitialized = FALSE; - BOOL LockEntered = FALSE; - BOOL InterfaceNotificationsInitialized = FALSE; - BOOL DeviceNotificationsInitialized = FALSE; - PDEVICE_CONTEXT DeviceContext; - - DeviceContext = (PDEVICE_CONTEXT)malloc(sizeof(DEVICE_CONTEXT)); - - if (DeviceContext == NULL) - { - Err = ERROR_OUTOFMEMORY; - goto cleanup; - } - - DeviceContext->DeviceInterfaceHandle = INVALID_HANDLE_VALUE; - DeviceContext->LockEnabled = FALSE; - DeviceContext->InterfaceNotificationsEnabled = FALSE; - DeviceContext->DeviceNotificationsEnabled = FALSE; - - InitializeCriticalSection(&DeviceContext->Lock); - DeviceContext->LockEnabled = TRUE; - - DeviceContext->Work = CreateThreadpoolWork(UnregisterWorkerThreadCallback, (PVOID)DeviceContext, NULL); - - if (DeviceContext->Work == NULL) - { - Err = GetLastError(); - WriteToErrorLog(L"Could not create worker thread callback", Err); - goto cleanup; - } - - DeviceContext->DeviceNotificationHandle = NULL; - DeviceContext->InterfaceNotificationHandle = NULL; - - // - // Register for device interface events to open and close the handle to - // the interface. - // - Err = RegisterInterfaceNotifications(DeviceContext); - - if (Err != ERROR_SUCCESS) - { - WriteToErrorLog(L"Could not register notifications", Err); - goto cleanup; - } - - DeviceContext->InterfaceNotificationsEnabled = TRUE; - - EnterCriticalSection(&DeviceContext->Lock); - LockEntered = TRUE; - - // - // The interface may already have arrived while registering for - // notifications. The lock could be moved earlier, but for sample - // purposes this is the proper way to initialize notifications. - // - if (DeviceContext->DeviceInterfaceHandle == INVALID_HANDLE_VALUE) - { - DeviceContext->DeviceInterfaceHandle = OpenDevice(FALSE); - } - - if (DeviceContext->DeviceInterfaceHandle != INVALID_HANDLE_VALUE) - { - Err = RegisterDeviceNotifications(DeviceContext); - - if (Err != ERROR_SUCCESS) - { - WriteToErrorLog(L"Could not register device notifications", Err); - goto cleanup; - } - - DeviceContext->DeviceNotificationsEnabled = TRUE; - } - - // - // If OpenDevice ends up returning INVALID_HANDLE_VALUE, that's fine - // since a notification for the interface will arrive later. - // - -cleanup: - - if (LockEntered) - { - LeaveCriticalSection(&DeviceContext->Lock); - } - - *Context = DeviceContext; - DeviceContext = NULL; - - if (DeviceContext != NULL) - { - CloseContext(DeviceContext); - } - - return Err; -} - - -/*++ - -Routine Description: - - Clean up the given PDEVICE_CONTEXT. - -Arguments: - - Context - The callback context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -CloseContext( - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - BOOL Unregister = FALSE; - - if (Context == NULL) - { - // - // Nothing to remove. - // - goto cleanup; - } - - EnterCriticalSection(&Context->Lock); - - if (!Context->Unregister) - { - // - // Unregister from the callback here. - // - Unregister = TRUE; - Context->Unregister = TRUE; - } - - LeaveCriticalSection(&Context->Lock); - - // - // Unregister from the interface first, so that re-appearance of the interface - // doesn't cause us to register device events again. - // - if (Context->InterfaceNotificationsEnabled) - { - Err = UnregisterInterfaceNotifications(Context); - - if (Err != ERROR_SUCCESS) - { - WriteToErrorLog(L"Could not unregister interface notifications", Err); - } - } - - if (Unregister) - { - if (Context->DeviceNotificationsEnabled) - { - Err = UnregisterDeviceNotifications(Context); - - if (Err != ERROR_SUCCESS) - { - WriteToErrorLog(L"Could not unregister device notifications", Err); - } - } - } - else - { - WaitForThreadpoolWorkCallbacks(Context->Work, FALSE); - } - - // - // No need to lock here, UnregisterDeviceNotifications will wait for all - // outstanding callbacks before returning. - // - if (Context->DeviceInterfaceHandle != INVALID_HANDLE_VALUE) - { - CloseHandle(Context->DeviceInterfaceHandle); - - Context->DeviceInterfaceHandle = INVALID_HANDLE_VALUE; - } - - if (Context->Work != NULL) - { - CloseThreadpoolWork(Context->Work); - } - - DeleteCriticalSection(&Context->Lock); - - free(Context); - -cleanup: - - return Err; -} - -/*++ - -Routine Description: - - Turns off all of the bar graph lights on the OSR USB FX2 device. - -Arguments: - - Context - The callback context - -Return Value: - - VOID - ---*/ -DWORD -ClearAllBars( - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - ULONG BytesReturned; - - BarGraphState.BarsAsUChar = 0; - - if (!DeviceIoControl(Context->DeviceInterfaceHandle, - IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY, - &BarGraphState, // Pointer to InBuffer - sizeof(BAR_GRAPH_STATE), // Length of InBuffer - NULL, // Pointer to OutBuffer - 0, // Length of OutBuffer - &BytesReturned, // BytesReturned - 0)) // Pointer to Overlapped structure - { - Err = GetLastError(); - WriteToErrorLog(L"DeviceIOControl", Err); - goto cleanup; - } - -cleanup: - - return Err; -} - - -/*++ - -Routine Description: - - Lights the next bar on the OSR USB FX2 device. - -Arguments: - - Context - The callback context - -Return Value: - - VOID - ---*/ -DWORD -LightNextBar( - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - ULONG BytesReturned; - - // - // Normalize to 0-7 - // - CurrentBar += 1; - - if (CurrentBar > 7) - { - CurrentBar = 0; - } - - BarGraphState.BarsAsUChar = 1 << (UCHAR)CurrentBar; - - if (!DeviceIoControl(Context->DeviceInterfaceHandle, - IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY, - &BarGraphState, // Pointer to InBuffer - sizeof(BAR_GRAPH_STATE), // Length of InBuffer - NULL, // Pointer to OutBuffer - 0, // Length of OutBuffer - &BytesReturned, // BytesReturned - 0)) // Pointer to Overlapped structure - { - Err = GetLastError(); - WriteToErrorLog(L"DeviceIOControl", Err); - goto cleanup; - } - -cleanup: - - return Err; -} - -/*++ - -Routine Description: - - Lights the next bar on the OSRFX2 device. - -Arguments: - - Context - The device context - -Return Value: - - A Win32 error code. - ---*/ -DWORD -ControlDevice( - _In_ PDEVICE_CONTEXT Context - ) -{ - DWORD Err = ERROR_SUCCESS; - - EnterCriticalSection(&Context->Lock); - - Err = ClearAllBars(Context); - - if (Err != ERROR_SUCCESS) - { - goto cleanup; - } - - Err = LightNextBar(Context); - - if (Err != ERROR_SUCCESS) - { - goto cleanup; - } - -cleanup: - - LeaveCriticalSection(&Context->Lock); - - return Err; -} \ No newline at end of file diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.h deleted file mode 100644 index 3b8be711f..000000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Main.h +++ /dev/null @@ -1,328 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - Main.h - -Abstract: - - Implements the functions to control the OSR USB FX2 device. - -Environment: - - User mode - ---*/ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -// {573E8C73-0CB4-4471-A1BF-FAB26C31D384} -DEFINE_GUID(GUID_DEVINTERFACE_OSRUSBFX2, - 0x573e8c73, 0xcb4, 0x4471, 0xa1, 0xbf, 0xfa, 0xb2, 0x6c, 0x31, 0xd3, 0x84); - -// -// Most device interface paths will fit into a buffer of this size. -// However, some could be longer, and a larger buffer or dynamically -// allocated buffer may be needed for robust code. -// -#define MAX_DEVPATH_LENGTH 1024 - -#pragma warning(push) -#pragma warning(disable:4201) // nameless struct/union -#pragma warning(disable:4214) // bit field types other than int - -typedef struct _DEVICE_CONTEXT { - HANDLE DeviceInterfaceHandle; - CRITICAL_SECTION Lock; - BOOL LockEnabled; - PTP_WORK Work; - BOOL Unregister; - HCMNOTIFICATION InterfaceNotificationHandle; - BOOL InterfaceNotificationsEnabled; - HCMNOTIFICATION DeviceNotificationHandle; - BOOL DeviceNotificationsEnabled; -} DEVICE_CONTEXT, *PDEVICE_CONTEXT; - -// -// Define the structures that will be used by the IOCTL -// interface to the driver -// - -// -// BAR_GRAPH_STATE -// -// BAR_GRAPH_STATE is a bit field structure with each -// bit corresponding to one of the bar graph on the -// OSRFX2 Development Board -// -#include -typedef struct _BAR_GRAPH_STATE { - - union { - - struct { - // - // Individual bars starting from the - // top of the stack of bars - // - // NOTE: There are actually 10 bars, - // but the very top two do not light - // and are not counted here - // - UCHAR Bar1 : 1; - UCHAR Bar2 : 1; - UCHAR Bar3 : 1; - UCHAR Bar4 : 1; - UCHAR Bar5 : 1; - UCHAR Bar6 : 1; - UCHAR Bar7 : 1; - UCHAR Bar8 : 1; - }; - - // - // The state of all the bar graph as a single - // UCHAR - // - UCHAR BarsAsUChar; - - }; - -}BAR_GRAPH_STATE, *PBAR_GRAPH_STATE; - -// -// SWITCH_STATE -// -// SWITCH_STATE is a bit field structure with each -// bit corresponding to one of the switches on the -// OSRFX2 Development Board -// -typedef struct _SWITCH_STATE { - - union { - struct { - // - // Individual switches starting from the - // left of the set of switches - // - UCHAR Switch1 : 1; - UCHAR Switch2 : 1; - UCHAR Switch3 : 1; - UCHAR Switch4 : 1; - UCHAR Switch5 : 1; - UCHAR Switch6 : 1; - UCHAR Switch7 : 1; - UCHAR Switch8 : 1; - }; - - // - // The state of all the switches as a single - // UCHAR - // - UCHAR SwitchesAsUChar; - - }; - - -}SWITCH_STATE, *PSWITCH_STATE; - -#include - -#pragma warning(pop) - -#define IOCTL_INDEX 0x800 -#define FILE_DEVICE_OSRUSBFX2 65500U - -#define IOCTL_OSRUSBFX2_GET_CONFIG_DESCRIPTOR CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ - IOCTL_INDEX, \ - METHOD_BUFFERED, \ - FILE_READ_ACCESS) - -#define IOCTL_OSRUSBFX2_RESET_DEVICE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ - IOCTL_INDEX + 1, \ - METHOD_BUFFERED, \ - FILE_WRITE_ACCESS) - -#define IOCTL_OSRUSBFX2_REENUMERATE_DEVICE CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ - IOCTL_INDEX + 3, \ - METHOD_BUFFERED, \ - FILE_WRITE_ACCESS) - -#define IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ - IOCTL_INDEX + 4, \ - METHOD_BUFFERED, \ - FILE_READ_ACCESS) - - -#define IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ - IOCTL_INDEX + 5, \ - METHOD_BUFFERED, \ - FILE_WRITE_ACCESS) - - -#define IOCTL_OSRUSBFX2_READ_SWITCHES CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ - IOCTL_INDEX + 6, \ - METHOD_BUFFERED, \ - FILE_READ_ACCESS) - - -#define IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ - IOCTL_INDEX + 7, \ - METHOD_BUFFERED, \ - FILE_READ_ACCESS) - - -#define IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY CTL_CODE(FILE_DEVICE_OSRUSBFX2, \ - IOCTL_INDEX + 8, \ - METHOD_BUFFERED, \ - FILE_WRITE_ACCESS) - -#define IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE CTL_CODE(FILE_DEVICE_OSRUSBFX2,\ - IOCTL_INDEX + 9, \ - METHOD_OUT_DIRECT, \ - FILE_READ_ACCESS) - -/*++ - -Routine Description: - -Lights the next bar on the OSRFX2 device. - -Arguments: - -Context - The device context - -Return Value: - -A Win32 error code. - ---*/ -DWORD -ControlDevice(PDEVICE_CONTEXT Context); - - -/*++ - -Routine Description: - - Sets the variables in this service to their default values. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID SetVariables(VOID); - - -/*++ - -Routine Description: - - Opens up the OSR USB FX2 device handle. - -Arguments: - - Synchronous - Whether or not this device should be - opened for synchronous access - -Return Value: - - The handle to the OSR USB FX2 device. - ---*/ -HANDLE OpenDevice(_In_ BOOL Synchronous); - - -/*++ - -Routine Description: - -Register for device notifications. - -Arguments: - -Context - The callback context - -Return Value: - -A Win32 error code. - ---*/ -DWORD RegisterDeviceNotifications(PDEVICE_CONTEXT Context); - - -/*++ - -Routine Description: - -Unregister for device notifications. - -Arguments: - -Context - The callback context - -Return Value: - -A Win32 error code. - ---*/ -DWORD UnregisterDeviceNotifications(PDEVICE_CONTEXT Context); - - -/*++ - -Routine Description: - -Initialize the given PDEVICE_CONTEXT. - -Arguments: - -Context - The callback context - -Return Value: - -A Win32 error code. - ---*/ -DWORD InitializeContext(PDEVICE_CONTEXT* Context); - - -/*++ - -Routine Description: - -Clean up the given PDEVICE_CONTEXT. - -Arguments: - -Context - The callback context - -Return Value: - -A Win32 error code. - ---*/ -DWORD CloseContext(PDEVICE_CONTEXT Context); \ No newline at end of file diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.cpp deleted file mode 100644 index fd3d497f8..000000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - SampleService.cpp - -Abstract: - - Provides a sample service class that derives from the service base class - - CServiceBase. The sample service logs the service start and stop - information to the Application event log, and shows how to run the main - function of the service in a thread pool worker thread. - -Environment: - - User mode - ---*/ - -#pragma region Includes -#include "SampleService.h" -#include "ThreadPool.h" -#pragma endregion - -/*++ - -Routine Description: - - The constructor of CSampleService. It initializes a new instance - of the CSampleService class. The optional parameters (CanStop, - CanShutdown and CanPauseContinue) allow you to specify whether the - service can be stopped, paused and continued, or be notified when system - shutdown occurs. Inherits properties from the class CServiceBase. - -Arguments: - - ServiceName - The name of the service - - CanStop - The service can be stopped - - CanShutdown - The service is notified when system shutdown occurs - - CanPauseContinue - The service can be paused and continued - -Return Value: - - VOID - ---*/ -CSampleService::CSampleService( - PWSTR ServiceName, - BOOL CanStop, - BOOL CanShutdown, - BOOL CanPauseContinue - ) -: CServiceBase(ServiceName, CanStop, CanShutdown, CanPauseContinue) -{ - m_fStopping = FALSE; - - // - // Create a manual-reset event that is not signaled at first to indicate - // the stopped signal of the service. - // - m_hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - - if (m_hStoppedEvent == NULL) - { - throw GetLastError(); - } -} - - -/*++ - -Routine Description: - - The virtual destructor of CSampleService. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -CSampleService::~CSampleService() -{ - if (m_hStoppedEvent) - { - CloseHandle(m_hStoppedEvent); - m_hStoppedEvent = NULL; - } -} - - -/*++ - -Routine Description: - - This function is executed when a Start command is sent to the - service by the SCM or when the operating system starts (for a service - that starts automatically). It specifies actions to take when the - service starts. In this code sample, OnStart logs a service-start - message to the Application log, and queues the main service function for - execution in a thread pool worker thread. - - NOTE: A service application is designed to be long running. Therefore, - it usually polls or monitors something in the system. The monitoring is - set up in the OnStart method. However, OnStart does not actually do the - monitoring. The OnStart method must return to the operating system after - the service's operation has begun. It must not loop forever or block. To - set up a simple monitoring mechanism, one general solution is to create - a timer in OnStart. The timer would then raise events in your code - periodically, at which time your service could do its monitoring. The - other solution is to spawn a new thread to perform the main service - functions, which is demonstrated in this code sample. - -Arguments: - - Argc - The number of command line arguments - - Argv - The array of command line arguments - -Return Value: - - VOID - ---*/ -VOID -CSampleService::OnStart( - DWORD Argc, - PWSTR *Argv - ) -{ - __debugbreak(); - - // - // Log a service start message to the Application log. - // - WriteToEventLog(L"SampleService in OnStart", - EVENTLOG_INFORMATION_TYPE); - - // - // Set up any variables the service needs. - // - SetVariables(); - - // - // Set up the context, and register for notifications. - // - InitializeContext(&m_Context); - - // - // Queue the main service function for execution in a worker thread. - // - CThreadPool::QueueUserWorkItem(&CSampleService::ServiceWorkerThread, this); -} - - -/*++ - -Routine Description: - - This method performs the main function of the service. It runs - on a thread pool worker thread. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -CSampleService::ServiceWorkerThread() -{ - // - // Periodically check if the service is stopping. - // - while (!m_fStopping) - { - // - // Perform main service function here... - // - - ControlDevice(m_Context); - - ::Sleep(2000); // Simulate some lengthy operations. - } - - // - // Signal the stopped event. - // - SetEvent(m_hStoppedEvent); -} - - -/*++ - -Routine Description: - - This function is executed when a Stop command is sent to the service by SCM. - It specifies actions to take when a service stops running. In this code - sample, OnStop logs a service-stop message to the Application log, and - waits for the finish of the main service function. - - Be sure to periodically call ReportServiceStatus() with - SERVICE_STOP_PENDING if the procedure is going to take a long time. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -CSampleService::OnStop() -{ - // - // Log a service stop message to the Application log. - // - WriteToEventLog(L"SampleService in OnStop", - EVENTLOG_INFORMATION_TYPE); - - // - // Indicate that the service is stopping and wait for the finish of the - // main service function (ServiceWorkerThread). - // - m_fStopping = TRUE; - - if (WaitForSingleObject(m_hStoppedEvent, INFINITE) != WAIT_OBJECT_0) - { - throw GetLastError(); - } - - // - // Clean up the context after the worker thread has finished. - // - CloseContext(m_Context); -} \ No newline at end of file diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.h deleted file mode 100644 index 73be42e95..000000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/SampleService.h +++ /dev/null @@ -1,187 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - SampleService.h - -Abstract: - - Provides a sample service class that derives from the service base class - - CServiceBase. The sample service logs the service start and stop - information to the Application event log, and shows how to run the main - function of the service in a thread pool worker thread. - -Environment: - - User mode - ---*/ - -#pragma once - -#include "ServiceBase.h" -#include "Main.h" - -class CSampleService : public CServiceBase -{ -public: - - /*++ - - Routine Description: - - The constructor of CSampleService. It initializes a new instance - of the CSampleService class. The optional parameters (CanStop, - CanShutdown and CanPauseContinue) allow you to specify whether the - service can be stopped, paused and continued, or be notified when system - shutdown occurs. Inherits properties from the class CServiceBase. - - Arguments: - - ServiceName - The name of the service - - CanStop - The service can be stopped - - CanShutdown - The service is notified when system shutdown occurs - - CanPauseContinue - The service can be paused and continued - - Return Value: - - VOID - - --*/ - CSampleService(PWSTR ServiceName, - BOOL CanStop = TRUE, - BOOL CanShutdown = TRUE, - BOOL CanPauseContinue = FALSE); - - /*++ - - Routine Description: - - The virtual destructor of CSampleService. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - virtual ~CSampleService(); - -protected: - - /*++ - - Routine Description: - - This function is executed when a Start command is sent to the - service by the SCM or when the operating system starts (for a service - that starts automatically). It specifies actions to take when the - service starts. In this code sample, OnStart logs a service-start - message to the Application log, and queues the main service function for - execution in a thread pool worker thread. - - NOTE: A service application is designed to be long running. Therefore, - it usually polls or monitors something in the system. The monitoring is - set up in the OnStart method. However, OnStart does not actually do the - monitoring. The OnStart method must return to the operating system after - the service's operation has begun. It must not loop forever or block. To - set up a simple monitoring mechanism, one general solution is to create - a timer in OnStart. The timer would then raise events in your code - periodically, at which time your service could do its monitoring. The - other solution is to spawn a new thread to perform the main service - functions, which is demonstrated in this code sample. - - Arguments: - - Argc - The number of command line arguments - - Argv - The array of command line arguments - - Return Value: - - VOID - - --*/ - virtual VOID OnStart(DWORD Argc, PWSTR *Argv); - - - /*++ - - Routine Description: - - This function is executed when a Stop command is sent to the service by SCM. - It specifies actions to take when a service stops running. In this code - sample, OnStop logs a service-stop message to the Application log, and - waits for the finish of the main service function. - - Be sure to periodically call ReportServiceStatus() with - SERVICE_STOP_PENDING if the procedure is going to take a long time. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - virtual VOID OnStop(); - - - /*++ - - Routine Description: - - This method performs the main function of the service. It runs - on a thread pool worker thread. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - VOID ServiceWorkerThread(); - -private: - - // - // Determines if the service is currently stopping. - // - BOOL m_fStopping; - - // - // The handle to wait for a stop event. - // - HANDLE m_hStoppedEvent; - - // - // The device context to manage notifications with. - // - // NOTE: - // Variables used for device notifications should normally be local. However, - // we must use a global variable here since there is a potential race condition - // when the service needs to restart during device installation that could - // cause the service to prevent the device from being restarted. So, this - // variable is global so that the service's OnStart and OnStart method can - // handle its creation and destruction. - // - PDEVICE_CONTEXT m_Context; -}; \ No newline at end of file diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.cpp deleted file mode 100644 index 4c20af2ef..000000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.cpp +++ /dev/null @@ -1,794 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - ServiceBase.cpp - -Abstract: - - Provides a base class for a service that will exist as part of a service - application. CServiceBase must be derived from when creating a new service - class. - -Environment: - - User mode - ---*/ - -#pragma region Includes -#include "ServiceBase.h" -#include "Main.h" -#include "Utils.h" -#include -#include -#pragma endregion - - -#pragma region Static Members - -// -// Initialize the singleton service instance. -// -CServiceBase *CServiceBase::s_service = NULL; - - -/*++ - -Routine Description: - - Register the executable for a service with the Service Control - Manager (SCM). After you call Run(ServiceBase), the SCM issues a Start - command, which results in a call to the OnStart method in the service. - This method blocks until the service has stopped. - -Arguments: - - Service - The reference to a CServiceBase object. It will become the - singleton service instance of this service application. - -Return Value: - - If the function succeeds, the return value is TRUE. If the function - fails, the return value is FALSE. To get extended error information, - call GetLastError. - ---*/ -BOOL -CServiceBase::Run( - CServiceBase &Service - ) -{ - s_service = &Service; - - SERVICE_TABLE_ENTRY serviceTable[] = - { - { Service.m_name, ServiceMain }, - { NULL, NULL } - }; - - // - // Connects the main thread of a service process to the service control - // manager, which causes the thread to be the service control dispatcher - // thread for the calling process. This call returns when the service has - // stopped. The process should simply terminate when the call returns. - // - return StartServiceCtrlDispatcher(serviceTable); -} - - -/*++ - -Routine Description: - - The entry point for the service. It registers the handler function - for the service and starts the service. - -Arguments: - - Argc - The number of command line arguments - - Argv - The array of command line arguments - -Return Value: - - VOID - ---*/ -VOID -WINAPI -CServiceBase::ServiceMain( - DWORD Argc, - PWSTR *Argv - ) -{ - assert(s_service != NULL); - - // - // Register the handler function for the service. - // - s_service->m_statusHandle = RegisterServiceCtrlHandler(s_service->m_name, - ServiceCtrlHandler); - - if (s_service->m_statusHandle == NULL) - { - throw GetLastError(); - } - - // - // Start the service. - // - s_service->Start(Argc, Argv); -} - - -/*++ - -Routine Description: - - Called by the SCM whenever a control code is sent to the service. - -Arguments: - - CtrlCode - The control code. This parameter can be one of - the following values: - - SERVICE_CONTROL_CONTINUE - SERVICE_CONTROL_INTERROGATE - SERVICE_CONTROL_NETBINDADD - SERVICE_CONTROL_NETBINDDISABLE - SERVICE_CONTROL_NETBINDREMOVE - SERVICE_CONTROL_PARAMCHANGE - SERVICE_CONTROL_PAUSE - SERVICE_CONTROL_SHUTDOWN - SERVICE_CONTROL_STOP - - This parameter can also be a user-defined control - code ranging from 128 to 255. - -Return Value: - - VOID - ---*/ -VOID -WINAPI -CServiceBase::ServiceCtrlHandler( - DWORD Ctrl - ) -{ - switch (Ctrl) - { - case SERVICE_CONTROL_STOP: - s_service->Stop(); - break; - case SERVICE_CONTROL_PAUSE: - s_service->Pause(); - break; - case SERVICE_CONTROL_CONTINUE: - s_service->Continue(); - break; - case SERVICE_CONTROL_SHUTDOWN: - s_service->Shutdown(); - break; - case SERVICE_CONTROL_INTERROGATE: - break; - default: - break; - } -} - -#pragma endregion - - -#pragma region Service Constructor and Destructor - -/*++ - -Routine Description: - - The constructor of CServiceBase. It initializes a new instance - of the CServiceBase class. The optional parameters (CanStop, - CanShutdown and CanPauseContinue) allow you to specify whether the - service can be stopped, paused and continued, or be notified when system - shutdown occurs. - -Arguments: - - ServiceName - The name of the service - - CanStop - The service can be stopped - - CanShutdown - The service is notified when system shutdown occurs - - CanPauseContinue - The service can be paused and continued - -Return Value: - - VOID - ---*/ -CServiceBase::CServiceBase( - PWSTR ServiceName, - BOOL CanStop, - BOOL CanShutdown, - BOOL CanPauseContinue - ) -{ - // - // Service name must be a valid string and cannot be NULL. - // - m_name = (ServiceName == NULL) ? L"" : ServiceName; - - m_statusHandle = NULL; - - // - // The service runs in its own process. - // - m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - - // - // The service is starting. - // - m_status.dwCurrentState = SERVICE_START_PENDING; - - // - // The accepted commands of the service. - // - DWORD dwControlsAccepted = 0; - - if (CanStop) - { - dwControlsAccepted |= SERVICE_ACCEPT_STOP; - } - - if (CanShutdown) - { - dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN; - } - - if (CanPauseContinue) - { - dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE; - } - - m_status.dwControlsAccepted = dwControlsAccepted; - - m_status.dwWin32ExitCode = NO_ERROR; - m_status.dwServiceSpecificExitCode = 0; - m_status.dwCheckPoint = 0; - m_status.dwWaitHint = 0; - - SetupEvents(); -} - - -/*++ - -Routine Description: - - The virtual destructor of CServiceBase. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -CServiceBase::~CServiceBase() -{ - DestroyEvents(); -} - -#pragma endregion - - -#pragma region Service Start, Stop, Pause, Continue, and Shutdown - -/*++ - -Routine Description: - - This function starts the service. It calls the OnStart virtual function - in which you can specify the actions to take when the service starts. If - an error occurs during the startup, the error will be logged in the - Application event log, and the service will be stopped. - -Arguments: - - Argc - The number of command line arguments - - Argv - The array of command line arguments - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::Start( - DWORD Argc, - PWSTR *Argv -) -{ - try - { - // - // Tell SCM that the service is starting. - // - SetServiceStatus(SERVICE_START_PENDING); - - // - // Perform service-specific initialization. - // - OnStart(Argc, Argv); - - // - // Tell SCM that the service is started. - // - SetServiceStatus(SERVICE_RUNNING); - } - catch (DWORD Error) - { - // - // Log the error. - // - WriteToErrorLog(L"Service Start", Error); - - // - // Set the service status to be stopped. - // - SetServiceStatus(SERVICE_STOPPED, Error); - } - catch (...) - { - // - // Log the error. - // - WriteToEventLog(L"Service failed to start.", EVENTLOG_ERROR_TYPE); - - // - // Set the service status to be stopped. - // - SetServiceStatus(SERVICE_STOPPED); - } -} - - -/*++ - -Routine Description: - - When implemented in a derived class, executes when a Start - command is sent to the service by the SCM or when the operating system - starts (for a service that starts automatically). Specifies actions to - take when the service starts. Be sure to periodically call - CServiceBase::SetServiceStatus() with SERVICE_START_PENDING if the - procedure is going to take long time. You may also consider spawning a - new thread in OnStart to perform time-consuming initialization tasks. - -Arguments: - - Argc - The number of command line arguments - - Argv - The array of command line arguments - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::OnStart( - DWORD Argc, - PWSTR *Argv -) -{ - SetVariables(); -} - - -/*++ - -Routine Description: - - This function stops the service. It calls the OnStop virtual - function in which you can specify the actions to take when the service - stops. If an error occurs, the error will be logged in the Application - event log, and the service will be restored to the original state. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::Stop() -{ - DWORD OriginalState = m_status.dwCurrentState; - - try - { - // - // Tell SCM that the service is stopping. - // - SetServiceStatus(SERVICE_STOP_PENDING); - - // - // Perform service-specific stop operations. - // - OnStop(); - - // - // Tell SCM that the service is stopped. - // - SetServiceStatus(SERVICE_STOPPED); - } - catch (DWORD Error) - { - // - // Log the error. - // - WriteToErrorLog(L"Service Stop", Error); - - // - // Set the orginal service status. - // - SetServiceStatus(OriginalState); - } - catch (...) - { - // - // Log the error. - // - WriteToEventLog(L"Service failed to stop.", EVENTLOG_ERROR_TYPE); - - // - // Set the orginal service status. - // - SetServiceStatus(OriginalState); - } -} - - -/*++ - -Routine Description: - - When implemented in a derived class, executes when a Stop - command is sent to the service by the SCM. Specifies actions to take - when a service stops running. Be sure to periodically call - CServiceBase::SetServiceStatus() with SERVICE_STOP_PENDING if the - procedure is going to take long time. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::OnStop() -{ -} - - -/*++ - -Routine Description: - - The function pauses the service if the service supports pause - and continue. It calls the OnPause virtual function in which you can - specify the actions to take when the service pauses. If an error occurs, - the error will be logged in the Application event log, and the service - will become running. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::Pause() -{ - try - { - // - // Tell SCM that the service is pausing. - // - SetServiceStatus(SERVICE_PAUSE_PENDING); - - // - // Perform service-specific pause operations. - // - OnPause(); - - // - // Tell SCM that the service is paused. - // - SetServiceStatus(SERVICE_PAUSED); - } - catch (DWORD Error) - { - // - // Log the error. - // - WriteToErrorLog(L"Service Pause", Error); - - // - // Tell SCM that the service is still running. - // - SetServiceStatus(SERVICE_RUNNING); - } - catch (...) - { - // - // Log the error. - // - WriteToEventLog(L"Service failed to pause.", EVENTLOG_ERROR_TYPE); - - // - // Tell SCM that the service is still running. - // - SetServiceStatus(SERVICE_RUNNING); - } -} - - -/*++ - -Routine Description: - - When implemented in a derived class, executes when a Pause - command is sent to the service by the SCM. Specifies actions to take - when a service pauses. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::OnPause() -{ -} - - -/*++ - -Routine Description: - - The function resumes normal functioning after being paused if - the service supports pause and continue. It calls the OnContinue virtual - function in which you can specify the actions to take when the service - continues. If an error occurs, the error will be logged in the - Application event log, and the service will still be paused. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::Continue() -{ - try - { - // - // Tell SCM that the service is resuming. - // - SetServiceStatus(SERVICE_CONTINUE_PENDING); - - // - // Perform service-specific continue operations. - // - OnContinue(); - - // - // Tell SCM that the service is running. - // - SetServiceStatus(SERVICE_RUNNING); - } - catch (DWORD Error) - { - // - // Log the error. - // - WriteToErrorLog(L"Service Continue", Error); - - // - // Tell SCM that the service is still paused. - // - SetServiceStatus(SERVICE_PAUSED); - } - catch (...) - { - // - // Log the error. - // - WriteToEventLog(L"Service failed to resume.", EVENTLOG_ERROR_TYPE); - - // - // Tell SCM that the service is still paused. - // - SetServiceStatus(SERVICE_PAUSED); - } -} - - -/*++ - -Routine Description: - - When implemented in a derived class, OnContinue runs when a - Continue command is sent to the service by the SCM. Specifies actions to - take when a service resumes normal functioning after being paused. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::OnContinue() -{ -} - - -/*++ - -Routine Description: - - The function executes when the system is shutting down. It - calls the OnShutdown virtual function in which you can specify what - should occur immediately prior to the system shutting down. If an error - occurs, the error will be logged in the Application event log. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::Shutdown() -{ - try - { - // - // Perform service-specific shutdown operations. - // - OnShutdown(); - - // - // Tell SCM that the service is stopped. - // - SetServiceStatus(SERVICE_STOPPED); - } - catch (DWORD Error) - { - // - // Log the error. - // - WriteToErrorLog(L"Service Shutdown", Error); - } - catch (...) - { - // - // Log the error. - // - WriteToEventLog(L"Service failed to shut down.", EVENTLOG_ERROR_TYPE); - } -} - - -/*++ - -Routine Description: - - When implemented in a derived class, executes when the system - is shutting down. Specifies what should occur immediately prior to the - system shutting down. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::OnShutdown() -{ -} - -#pragma endregion - - -#pragma region Helper Functions - -/*++ - -Routine Description: - - The function sets the service status and reports the status to the SCM. - -Arguments: - - CurrentState - The current state of the service - - Win32ExitCode - The error code to report - - WaitHint - The estimated time for pending operation, in milliseconds - -Return Value: - - VOID - ---*/ -VOID -CServiceBase::SetServiceStatus( - DWORD CurrentState, - DWORD Win32ExitCode, - DWORD WaitHint - ) -{ - static DWORD CheckPoint = 1; - - // - // Fill in the SERVICE_STATUS structure of the service. - // - - m_status.dwCurrentState = CurrentState; - m_status.dwWin32ExitCode = Win32ExitCode; - m_status.dwWaitHint = WaitHint; - - m_status.dwCheckPoint = ((CurrentState == SERVICE_RUNNING) || - (CurrentState == SERVICE_STOPPED)) ? 0 : - CheckPoint++; - - // - // Report the status of the service to the SCM. - // - ::SetServiceStatus(m_statusHandle, &m_status); -} - -#pragma endregion \ No newline at end of file diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.h deleted file mode 100644 index 106597e12..000000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceBase.h +++ /dev/null @@ -1,423 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - ServiceBase.cpp - -Abstract: - - Provides a base class for a service that will exist as part of a service - application. CServiceBase must be derived from when creating a new service - class. - -Environment: - - User mode - ---*/ - -#pragma once - -#include -#include "Utils.h" - -class CServiceBase -{ -public: - - /*++ - - Routine Description: - - Register the executable for a service with the Service Control - Manager (SCM). After you call Run(ServiceBase), the SCM issues a Start - command, which results in a call to the OnStart method in the service. - This method blocks until the service has stopped. - - Arguments: - - Service - The reference to a CServiceBase object. It will become the - singleton service instance of this service application. - - Return Value: - - If the function succeeds, the return value is TRUE. If the function - fails, the return value is FALSE. To get extended error information, - call GetLastError. - - --*/ - static BOOL Run(CServiceBase &service); - - - /*++ - - Routine Description: - - The constructor of CServiceBase. It initializes a new instance - of the CServiceBase class. The optional parameters (CanStop, - CanShutdown and CanPauseContinue) allow you to specify whether the - service can be stopped, paused and continued, or be notified when system - shutdown occurs. - - Arguments: - - ServiceName - The name of the service - - CanStop - The service can be stopped - - CanShutdown - The service is notified when system shutdown occurs - - CanPauseContinue - The service can be paused and continued - - Return Value: - - VOID - - --*/ - CServiceBase(PWSTR ServiceName, - BOOL CanStop = TRUE, - BOOL CanShutdown = TRUE, - BOOL CanPauseContinue = FALSE); - - - /*++ - - Routine Description: - - The virtual destructor of CServiceBase. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - virtual ~CServiceBase(); - - - /*++ - - Routine Description: - - This function stops the service. It calls the OnStop virtual - function in which you can specify the actions to take when the service - stops. If an error occurs, the error will be logged in the Application - event log, and the service will be restored to the original state. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - VOID Stop(); - -protected: - - /*++ - - Routine Description: - - When implemented in a derived class, executes when a Start - command is sent to the service by the SCM or when the operating system - starts (for a service that starts automatically). Specifies actions to - take when the service starts. Be sure to periodically call - CServiceBase::SetServiceStatus() with SERVICE_START_PENDING if the - procedure is going to take long time. You may also consider spawning a - new thread in OnStart to perform time-consuming initialization tasks. - - Arguments: - - Argc - The number of command line arguments - - Argv - The array of command line arguments - - Return Value: - - VOID - - --*/ - virtual VOID OnStart(DWORD Argc, PWSTR *Argv); - - - /*++ - - Routine Description: - - When implemented in a derived class, executes when a Stop - command is sent to the service by the SCM. Specifies actions to take - when a service stops running. Be sure to periodically call - CServiceBase::SetServiceStatus() with SERVICE_STOP_PENDING if the - procedure is going to take long time. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - virtual VOID OnStop(); - - - /*++ - - Routine Description: - - When implemented in a derived class, executes when a Pause - command is sent to the service by the SCM. Specifies actions to take - when a service pauses. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - virtual VOID OnPause(); - - - /*++ - - Routine Description: - - When implemented in a derived class, OnContinue runs when a - Continue command is sent to the service by the SCM. Specifies actions to - take when a service resumes normal functioning after being paused. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - virtual VOID OnContinue(); - - - /*++ - - Routine Description: - - When implemented in a derived class, executes when the system - is shutting down. Specifies what should occur immediately prior to the - system shutting down. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - virtual VOID OnShutdown(); - - - /*++ - - Routine Description: - - The function sets the service status and reports the status to the SCM. - - Arguments: - - CurrentState - The current state of the service - - Win32ExitCode - The error code to report - - WaitHint - The estimated time for pending operation, in milliseconds - - Return Value: - - VOID - - --*/ - VOID SetServiceStatus(DWORD CurrentState, - DWORD Win32ExitCode = NO_ERROR, - DWORD WaitHint = 0); - -private: - - /*++ - - Routine Description: - - The entry point for the service. It registers the handler function - for the service and starts the service. - - Arguments: - - Argc - The number of command line arguments - - Argv - The array of command line arguments - - Return Value: - - VOID - - --*/ - static VOID WINAPI ServiceMain(DWORD Argc, PWSTR *Argv); - - - /*++ - - Routine Description: - - Called by the SCM whenever a control code is sent to the service. - - Arguments: - - CtrlCode - The control code. This parameter can be one of - the following values: - - SERVICE_CONTROL_CONTINUE - SERVICE_CONTROL_INTERROGATE - SERVICE_CONTROL_NETBINDADD - SERVICE_CONTROL_NETBINDDISABLE - SERVICE_CONTROL_NETBINDREMOVE - SERVICE_CONTROL_PARAMCHANGE - SERVICE_CONTROL_PAUSE - SERVICE_CONTROL_SHUTDOWN - SERVICE_CONTROL_STOP - - This parameter can also be a user-defined control - code ranging from 128 to 255. - - Return Value: - - VOID - - --*/ - static VOID WINAPI ServiceCtrlHandler(DWORD Ctrl); - - - /*++ - - Routine Description: - - This function starts the service. It calls the OnStart virtual function - in which you can specify the actions to take when the service starts. If - an error occurs during the startup, the error will be logged in the - Application event log, and the service will be stopped. - - Arguments: - - Argc - The number of command line arguments - - Argv - The array of command line arguments - - Return Value: - - VOID - - --*/ - VOID Start(DWORD Argc, PWSTR *Argv); - - - /*++ - - Routine Description: - - The function pauses the service if the service supports pause - and continue. It calls the OnPause virtual function in which you can - specify the actions to take when the service pauses. If an error occurs, - the error will be logged in the Application event log, and the service - will become running. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - VOID Pause(); - - - /*++ - - Routine Description: - - The function resumes normal functioning after being paused if - the service supports pause and continue. It calls the OnContinue virtual - function in which you can specify the actions to take when the service - continues. If an error occurs, the error will be logged in the - Application event log, and the service will still be paused. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - VOID Continue(); - - - /*++ - - Routine Description: - - The function executes when the system is shutting down. It - calls the OnShutdown virtual function in which you can specify what - should occur immediately prior to the system shutting down. If an error - occurs, the error will be logged in the Application event log. - - Arguments: - - VOID - - Return Value: - - VOID - - --*/ - VOID Shutdown(); - - - // - // The singleton service instance. - // - static CServiceBase *s_service; - - // - // The name of the service. - // - PWSTR m_name; - - // - // The status of the service. - // - SERVICE_STATUS m_status; - - // - // The service status handle. - // - SERVICE_STATUS_HANDLE m_statusHandle; -}; \ No newline at end of file diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.cpp new file mode 100644 index 000000000..f66168500 --- /dev/null +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.cpp @@ -0,0 +1,375 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + ServiceWin32API.cpp + +Abstract: + + Implements functions to start/run/stop the service. + +Environment: + + User mode + +--*/ + +#include "stdafx.h" + +// +// Settings of the service +// +#define SERVICE_NAME L"OsrUsbFx2UmUserSvc" +#define SERVICE_FLAGS_RUNNING 0x1 + +// +// Service context +// +SERVICE_STATUS_HANDLE SvcStatusHandle = NULL; +volatile LONG SvcControlFlags = 0; +HANDLE SvcStoppedEvent = NULL; +HANDLE SvcStopRequestEvent = NULL; +HANDLE SvcStopWaitObject = NULL; + +// +// Device interface context +// +HCMNOTIFICATION InterfaceNotificationHandle = NULL; +SRWLOCK DeviceListLock = SRWLOCK_INIT; +DEVICE_LIST_ENTRY DeviceList; + +// +// Debugging support during development time +// +//#define DEBUG_SUPPORT + +/*++ + +Routine Description: + + Entry point for the service. + +Arguments: + + Argc - The number of command line arguments + + Argv - The array of command line arguments + +Return Value: + + VOID + +--*/ +INT +wmain( + INT Argc, + WCHAR *Argv[] + ) +{ + UNREFERENCED_PARAMETER(Argc); + UNREFERENCED_PARAMETER(Argv); + + SERVICE_TABLE_ENTRY serviceTable[] = + { + { SERVICE_NAME, ServiceMain }, + { NULL, NULL } + }; + + return StartServiceCtrlDispatcher(serviceTable); +} + +VOID WINAPI ServiceMain( + DWORD Argc, + PWSTR *Argv + ) +{ + DWORD Err = ERROR_SUCCESS; + + UNREFERENCED_PARAMETER(Argc); + UNREFERENCED_PARAMETER(Argv); + + // + // Initialize global variables + // + InitializeDeviceListHead(&DeviceList); + +#ifdef DEBUG_SUPPORT + + while (!IsDebuggerPresent()) { + Sleep(1000); + } + + __debugbreak(); + +#endif + + SvcStatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, + ServiceCtrlHandler); + + if (SvcStatusHandle == NULL) + { + Err = GetLastError(); + goto cleanup; + } + + UpdateServiceStatus(SvcStatusHandle, + SERVICE_START_PENDING, + ERROR_SUCCESS); + + // + // Setup device interface context + // + Err = SetupDeviceInterfaceContext(); + + UpdateServiceStatus(SvcStatusHandle, + SERVICE_START_PENDING, + ERROR_SUCCESS); + + // + // Initialize device control + // + OsrFx2InitializeDevice(); + + // + // Register callback function for stop event + // + SvcStopRequestEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (SvcStopRequestEvent == NULL) + { + Err = GetLastError(); + goto cleanup; + } + + if (!RegisterWaitForSingleObject(&SvcStopWaitObject, + SvcStopRequestEvent, + ServiceStopCallback, + NULL, + INFINITE, + WT_EXECUTEONLYONCE | WT_EXECUTEINPERSISTENTTHREAD)) + { + Err = GetLastError(); + goto cleanup; + } + + // + // Create stopped event for the running worker thread + // + SvcStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (SvcStoppedEvent == NULL) + { + Err = GetLastError(); + goto cleanup; + } + + UpdateServiceStatus(SvcStatusHandle, + SERVICE_START_PENDING, + ERROR_SUCCESS); + + // + // Queue the main service function for execution in a worker thread. + // + QueueUserWorkItem(&ServiceRunningWorkerThread, + NULL, + WT_EXECUTELONGFUNCTION); + + UpdateServiceStatus(SvcStatusHandle, + SERVICE_RUNNING, + ERROR_SUCCESS); + +cleanup: + + if (Err != ERROR_SUCCESS) + { + ServiceStop(Err); + } +} + +VOID +WINAPI +ServiceCtrlHandler( + DWORD Ctrl + ) +{ + switch (Ctrl) + { + case SERVICE_CONTROL_STOP: + // + // Set service stop event + // + UpdateServiceStatus(SvcStatusHandle, SERVICE_STOP_PENDING, ERROR_SUCCESS); + SetEvent(SvcStopRequestEvent); + break; + + default: + break; + } +} + +#define SERVICE_WAIT_HINT_TIME 30000 // 30 seconds + +BOOL +UpdateServiceStatus( + __in_opt SERVICE_STATUS_HANDLE hSvcHandle, + __in DWORD dwCurrentState, + __in DWORD dwWin32ExitCode + ) +{ + SERVICE_STATUS SvcStatus; + + static DWORD dwCheckPoint = 1; + + SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + SvcStatus.dwCurrentState = dwCurrentState; + SvcStatus.dwWin32ExitCode = dwWin32ExitCode; + SvcStatus.dwServiceSpecificExitCode = ERROR_SUCCESS; + + if (dwCurrentState == SERVICE_START_PENDING) + { + SvcStatus.dwControlsAccepted = 0; + } + else + { + SvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; + } + + if ((dwCurrentState == SERVICE_RUNNING) || + (dwCurrentState == SERVICE_STOPPED)) + { + SvcStatus.dwCheckPoint = 0; + SvcStatus.dwWaitHint = 0; + } + else + { + SvcStatus.dwCheckPoint = dwCheckPoint++; + SvcStatus.dwWaitHint = SERVICE_WAIT_HINT_TIME; + } + + return SetServiceStatus(hSvcHandle, &SvcStatus); +} + +DWORD +WINAPI +ServiceRunningWorkerThread( + _In_ PVOID lpThreadParameter + ) +{ + PDEVICE_CONTEXT DeviceContext = NULL; + PDEVICE_LIST_ENTRY Link = NULL; + + UNREFERENCED_PARAMETER(lpThreadParameter); + + InterlockedOr(&SvcControlFlags, SERVICE_FLAGS_RUNNING); + + // + // Periodically check if the service is stopping. + // + while ((InterlockedOr(&SvcControlFlags, 0) & SERVICE_FLAGS_RUNNING) != 0) + { + AcquireSRWLockShared(&DeviceListLock); + + for (Link = DeviceList.Flink; Link != &DeviceList; Link = Link->Flink) + { + DeviceContext = CONTAINING_DEVICE_RECORD(Link); + + OsrFx2ControlDevice(DeviceContext); + } + + ReleaseSRWLockShared(&DeviceListLock); + + Sleep(2000); // Simulate some lengthy operations. + } + + // + // Signal the stopped event. + // + SetEvent(SvcStoppedEvent); + + return 0; +} + +VOID +CALLBACK +ServiceStopCallback( + _In_ PVOID lpParameter, + _In_ BOOLEAN TimerOrWaitFired + ) +{ + UNREFERENCED_PARAMETER(TimerOrWaitFired); + + // + // Since wait object can not be unregistered in callback function, queue + // another thread + // + QueueUserWorkItem(ServiceStopWorkerThread, + lpParameter, + WT_EXECUTEDEFAULT); +} + +DWORD +WINAPI +ServiceStopWorkerThread( + _In_ PVOID lpThreadParameter + ) +{ + UNREFERENCED_PARAMETER(lpThreadParameter); + + ServiceStop(ERROR_SUCCESS); + + return 0; +} + +VOID +ServiceStop( + _In_ DWORD ExitCode + ) +{ + if (SvcStatusHandle == NULL) + { + return; + } + + UpdateServiceStatus(SvcStatusHandle, SERVICE_STOP_PENDING, ExitCode); + + // + // Notify the working thread to stop + // + if ((InterlockedOr(&SvcControlFlags, 0) & SERVICE_FLAGS_RUNNING) != 0) + { + InterlockedAnd(&SvcControlFlags, ~SERVICE_FLAGS_RUNNING); + WaitForSingleObject(SvcStoppedEvent, INFINITE); + } + + // + // Clean up device context after the worker thread has finished. + // + CleanupDeviceInterfaceContext(); + + // + // cleanup work + // + if (SvcStopWaitObject != NULL) + { + UnregisterWait(SvcStopWaitObject); + } + + if (SvcStopRequestEvent != NULL) + { + CloseHandle(SvcStopRequestEvent); + } + + if (SvcStoppedEvent != NULL) + { + CloseHandle(SvcStoppedEvent); + } + + UpdateServiceStatus(SvcStatusHandle, SERVICE_STOPPED, ExitCode); +} diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.h new file mode 100644 index 000000000..e469ca9dc --- /dev/null +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ServiceWin32API.h @@ -0,0 +1,56 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +--*/ + +#pragma once + +VOID +WINAPI +ServiceMain( + DWORD Argc, + PWSTR *Argv + ); + +VOID +WINAPI +ServiceCtrlHandler( + DWORD Ctrl + ); + +BOOL +UpdateServiceStatus( + __in_opt SERVICE_STATUS_HANDLE hSvcHandle, + __in DWORD dwCurrentState, + __in DWORD dwWin32ExitCode + ); + +VOID +CALLBACK +ServiceStopCallback( + _In_ PVOID lpParameter, + _In_ BOOLEAN TimerOrWaitFired + ); + +VOID +ServiceStop( + _In_ DWORD ExitCode + ); + +DWORD +WINAPI +ServiceRunningWorkerThread( + _In_ PVOID lpThreadParameter + ); + +DWORD +WINAPI +ServiceStopWorkerThread( + _In_ PVOID lpThreadParameter + ); diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ThreadPool.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ThreadPool.h deleted file mode 100644 index 3d8515378..000000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/ThreadPool.h +++ /dev/null @@ -1,80 +0,0 @@ -/****************************** Module Header ******************************\ -* Module Name: ThreadPool.h -* Project: CppWindowsService -* Copyright (c) Microsoft Corporation. -* -* The class was designed by Kenny Kerr. It provides the ability to queue -* simple member functions of a class to the Windows thread pool. -* -* Using the thread pool is simple and feels natural in C++. -* -* class CSampleService -* { -* public: -* -* void AsyncRun() -* { -* CThreadPool::QueueUserWorkItem(&Service::Run, this); -* } -* -* void Run() -* { -* // Some lengthy operation -* } -* }; -* -* Kenny Kerr spends most of his time designing and building distributed -* applications for the Microsoft Windows platform. He also has a particular -* passion for C++ and security programming. Reach Kenny at -* http://weblogs.asp.net/kennykerr/ or visit his Web site: -* http://www.kennyandkarin.com/Kenny/. -* -* This source is subject to the Microsoft Public License. -* See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL. -* All other rights reserved. -* -* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, -* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. -\***************************************************************************/ - -#pragma once - -#include - - -class CThreadPool -{ -public: - - template - static void QueueUserWorkItem(void (T::*function)(void), - T *object, ULONG flags = WT_EXECUTELONGFUNCTION) - { - typedef std::pair CallbackType; - std::auto_ptr p(new CallbackType(function, object)); - - if (::QueueUserWorkItem(ThreadProc, p.get(), flags)) - { - // The ThreadProc now has the responsibility of deleting the pair. - p.release(); - } - else - { - throw GetLastError(); - } - } - -private: - - template - static DWORD WINAPI ThreadProc(PVOID context) - { - typedef std::pair CallbackType; - - std::auto_ptr p(static_cast(context)); - - (p->second->*p->first)(); - return 0; - } -}; \ No newline at end of file diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.cpp b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.cpp deleted file mode 100644 index e8fc87ee5..000000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - Utils.cpp - -Abstract: - - Provides utility function to SampleApp.cpp. - -Environment: - - User mode - ---*/ - -#include "Utils.h" - -// -// Service trace event provider -// {54a25c42-cd91-4210-98cc-c3447b56e447} -// -EXTERN_C __declspec(selectany) const GUID SERVICE_PROVIDER_GUID = { 0x54a25c42, 0xcd91, 0x4210,{ 0x98, 0xcc, 0xc3, 0x44, 0x7b, 0x56, 0xe4, 0x47 } }; - -REGHANDLE m_etwRegHandle; - - -/*++ - -Routine Description: - - Sets up logging. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -SetupEvents() -{ - NTSTATUS status = EventRegister(&SERVICE_PROVIDER_GUID, - nullptr, - nullptr, - &m_etwRegHandle); - - if (status != ERROR_SUCCESS) - { - wprintf(L"Provider not registered. EventRegister failed with error: 0x%08X\n", status); - } -} - - -/*++ - -Routine Description: - - Destroys logging. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID -DestroyEvents() -{ - if (m_etwRegHandle != NULL) - { - EventUnregister(m_etwRegHandle); - } -} - - -/*++ - -Routine Description: - - Log a message. - -Arguments: - - Message - The string message to be logged - - Level - The type of event to be logged. This parameter can - be one of the following values: - - TRACE_LEVEL_CRITICAL - TRACE_LEVEL_ERROR - TRACE_LEVEL_WARNING - TRACE_LEVEL_INFORMATION - TRACE_LEVEL_VERBOSE - -Return Value: - - VOID - ---*/ -VOID -WriteToEventLog( - PWSTR Message, - BYTE Level - ) -{ - if (m_etwRegHandle != NULL) - { - EventWriteString(m_etwRegHandle, Level, 0, Message); - } -} - - -/*++ - -Routine Description: - - Log an error message. - -Arguments: - - Function - The function that gives the error - - Error - The error code - -Return Value: - - VOID - ---*/ -VOID -WriteToErrorLog( - PWSTR Function, - DWORD Error - ) -{ - WCHAR Message[260]; - - StringCchPrintf(Message, ARRAYSIZE(Message), - L"%ws failed with error: 0x%08x", Function, Error); - - WriteToEventLog(Message, TRACE_LEVEL_ERROR); -} \ No newline at end of file diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.h deleted file mode 100644 index b619f4617..000000000 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/Utils.h +++ /dev/null @@ -1,111 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - Utils.cpp - -Abstract: - - Provides utility function to SampleApp.cpp. - -Environment: - - User mode - ---*/ - -#pragma once - -#include -#include -#include -#include - -/*++ - -Routine Description: - - Sets up logging. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID SetupEvents(); - - -/*++ - -Routine Description: - - Destroys logging. - -Arguments: - - VOID - -Return Value: - - VOID - ---*/ -VOID DestroyEvents(); - - -/*++ - -Routine Description: - - Log a message. - -Arguments: - - Message - The string message to be logged - - Level - The type of event to be logged. This parameter can - be one of the following values: - - TRACE_LEVEL_CRITICAL - TRACE_LEVEL_ERROR - TRACE_LEVEL_WARNING - TRACE_LEVEL_INFORMATION - TRACE_LEVEL_VERBOSE - -Return Value: - - VOID - ---*/ -VOID WriteToEventLog(PWSTR Message, BYTE Level); - - -/*++ - -Routine Description: - - Log an error message. - -Arguments: - - Function - The function that gives the error - - Error - The error code - -Return Value: - - VOID - ---*/ -VOID WriteToErrorLog(PWSTR Function, DWORD Error); \ No newline at end of file diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.inx b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.inx deleted file mode 100644 index 61e1e958c57e76d222c147539c30f5ea2c5bef91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3190 zcmbW3ZEspf5QXP+r2dC1%QQ(Fzv3u%t$rXFJC*}j#?FhH%A!CV%eAopC$XaZ^|a5~ z*##~Jgd%kB-Iv*!vuDrD^52hLTeIKncYeRvBioJdvUTm&?yYB+c441vV3|F!mObTL zWvs}d#za_qJX~}=x&iJZd zV$BKf8vXZ-)ba1}-bZYX>WG!X@Qm3?^ipA^dhbHy3Nacnt`I6}m6_Lkg+?poqs+(| zeYFo5dl|9Rh%HRAukxHmU#E;aE0r9gy!XkyD5iGq`>E19A@ZxZ(-Kh+LnPm|^Sg$% zaPNocwctTMoN=)tj>VXmFN6Da==m8sPsfa&U{w!Xe6+8&Y3Hyd>}Ry@qJH`)sD*x95#uT<*+19}f+kyhr~5xdsj_MYo%X@g&hn4E(NB>0WpTV9IDq@jv3EOfx{ zp7R{7*b14s7C6za{zA{f(Z^bm{|++^dKdJRb$84P!Jj-!wjB4+#`;T$C1o!&BX4Ce zHyITM**CCKE`JGFJIr@E6J_)bKDE#Msso~3g5Fnuv*+-!#ZwHwO|Tc~Z(*^*dz)U1 z*0#N%wL@!@6+3v|33e^MEq>efJ;XT^}c84epX~Zg+-7#Q?3rz#u@Buca5OnXY4}fqpXs~m&0B>`s`J! z4^|~ad-zVuN*Pv&OwRUqP9BZtgKAX+C6(<%tf%L;&WS$9`>$lTD(pF@w-ruAXdSWi zBt0r)_BesQUGb!|=tuP~dKw*aDJgqnjF;(A(r#0fjiG)Ll4Rj}am3=hfuo#-WS+N& zYknTZ>O{p%?3Kvo_QafXB$cgm#_PG?W?*9Ws>Rgv(D!zTqVai*`a<@%^xhIVXiV=%%l8HRq$AqPE*%?o4vL0TbFwBh1Lb!@8nVb2O<{l@Bjb+ diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj index 6965d745b..60174c569 100644 --- a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/osrfx2_DCHU_usersvc.vcxproj @@ -23,7 +23,7 @@ osrfx2_DCHU_usersvc Win32Proj osrfx2_DCHU_usersvc - 10.0.16299.0 + 10.0.17134.0 @@ -93,14 +93,13 @@ - Full + Disabled WIN32;_CONSOLE;%(PreprocessorDefinitions) - true EnableFastChecks MultiThreaded - Level3 + Level4 EditAndContinue @@ -108,11 +107,11 @@ Console MachineX86 onecoreuap.lib;%(AdditionalDependencies); + false - Full true WIN32;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded @@ -121,6 +120,7 @@ Level3 ProgramDatabase + Full true @@ -138,8 +138,7 @@ Full WIN32;_CONSOLE;%(PreprocessorDefinitions) - true - EnableFastChecks + Default MultiThreaded @@ -182,18 +181,15 @@ - - - - - + + + - - - - - + + + + diff --git a/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/stdafx.h b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/stdafx.h new file mode 100644 index 000000000..7bd67951e --- /dev/null +++ b/general/DCHU/osrfx2_DCHU_base/osrfx2_DCHU_usersvc/stdafx.h @@ -0,0 +1,26 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +--*/ + +#pragma once + +#include +#include + +// +// Device context +// +#include + +#include + +#include "ServiceWin32API.h" +#include "DeviceContext.h" +#include "DeviceControl.h"