1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxTelemetry.cpp
8 
9 Abstract:
10 
11     This module implements a telemetry methods.
12 
13 Author:
14 
15 
16 
17 Environment:
18 
19     Both kernel and user mode
20 
21 Revision History:
22 
23 Notes:
24 
25 --*/
26 
27 
28 
29 #include "fxsupportpch.hpp"
30 
31 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
32 #include "fxldr.h"
33 #include <ntstrsafe.h>
34 #else
35 #include "driverframeworks-usermode-umevents.h"
36 #include "fxldrum.h"
37 #endif
38 
39 extern "C" {
40 #if defined(EVENT_TRACING)
41 #include "fxtelemetry.tmh"
42 #endif
43 }
44 
45 #if defined(__cplusplus)
46 extern "C" {
47 #endif
48 
49 
50 
51 
52 
53 VOID
54 GetNameFromPath(
55     _In_ PCUNICODE_STRING Path,
56     _Out_ PUNICODE_STRING Name
57     )
58 /*++
59 
60 Routine Description:
61 
62     Given a potential full path name, return just the filename portion, OR,
63     Given a potential full registry path name, return just the subkey portion.
64 
65     Pointer to the filename protion in the full path name string, OR,
66     Pointer to the subkey portion in the full registry path name.
67 
68 Arguments:
69 
70     Path - Pointer to the full path name string.
71 
72     Name - Pointer to receive the name
73 
74 Return Value:
75     None
76 
77 --*/
78 {
79     BOOLEAN foundSlash;
80 
81     ASSERT(Path != NULL);
82 
83     //
84     // Ideally a check of Path->Length == 0 would be sufficient except that
85     // PreFAST thinks that Length can be odd, so it thinks Length == 1 is possible.
86     // Comparing Length < sizeof(WCHAR) satisfies PreFAST and keeps the logic
87     // at runtime correct.
88     //
89     if (Path->Length < sizeof(WCHAR)) {
90         RtlZeroMemory(Name, sizeof(UNICODE_STRING));
91         return;
92     }
93 
94     //
95     // Initialize Name to point to the last WCHAR of the buffer and we will work
96     // our way backwards to the beginning of the string or a \
97     //
98 
99     Name->Buffer = WDF_PTR_ADD_OFFSET_TYPE(Path->Buffer,
100                                            Path->Length - sizeof(WCHAR),
101                                            PWCH);
102     Name->Length = sizeof(WCHAR);
103     foundSlash = FALSE;
104 
105     while (Name->Buffer >= Path->Buffer) {
106         if (*Name->Buffer == L'\\') {
107             //
108             // Skip the \ in the buffer moving forward a character and adjusting
109             // the length
110             //
111             foundSlash = TRUE;
112             Name->Buffer++;
113             Name->Length -= sizeof(WCHAR);
114             break;
115         }
116 
117         //
118         // Move backwards in the string
119         //
120         Name->Buffer--;
121         Name->Length += sizeof(WCHAR);
122     }
123 
124     if (foundSlash && Name->Length == 0) {
125         //
126         // Handle the case where a slash was found and it is the only character
127         //
128         Name->Buffer = NULL;
129     }
130     else if (foundSlash == FALSE) {
131         //
132         // Handle the case where no slash was found. In this case, Name->Buffer
133         // points to one WCHAR before the beginning of the string.
134         //
135         Name->Length -= sizeof(WCHAR);
136         Name->Buffer++;
137     }
138 
139     //
140     // Need to set MaximumLength to the same value as Length so that the struct
141     // format is valid.
142     //
143     Name->MaximumLength = Name->Length;
144 }
145 
146 #if defined(__cplusplus)
147 }
148 #endif
149 
150