1cb809d9a779872fa74ee0a9091f19fbe071e5e3
[openafs.git] / src / WINNT / afsd / rpc_srvsvc.c
1 /*
2  * Copyright (c) 2009 Secure Endpoints Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation
6  * files (the "Software"), to deal in the Software without
7  * restriction, including without limitation the rights to use, copy,
8  * modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24
25 #include<windows.h>
26 #include <wchar.h>
27 #define _CRT_RAND_S
28 #include <stdlib.h>
29 #include <strsafe.h>
30 #include <svrapi.h>
31 #include "ms-srvsvc.h"
32 #include "msrpc.h"
33 #include "afsd.h"
34 #include <WINNT/afsreg.h>
35 #define AFS_VERSION_STRINGS
36 #include "AFS_component_version_number.h"
37
38 #pragma warning( disable: 4027 )  /* func w/o formal parameter list */
39
40 /* Do not pull in lmserver.h */
41 //
42 // The platform ID indicates the levels to use for platform-specific
43 // information.
44 //
45 #define SV_PLATFORM_ID_DOS 300
46 #define SV_PLATFORM_ID_OS2 400
47 #define SV_PLATFORM_ID_NT  500
48 #define SV_PLATFORM_ID_OSF 600
49 #define SV_PLATFORM_ID_VMS 700
50 #define SV_PLATFORM_ID_AFS 800
51 //
52 //      Bit-mapped values for svX_type fields. X = 1, 2 or 3.
53 //
54 #define SV_TYPE_WORKSTATION         0x00000001
55 #define SV_TYPE_SERVER              0x00000002
56 #define SV_TYPE_SQLSERVER           0x00000004
57 #define SV_TYPE_DOMAIN_CTRL         0x00000008
58 #define SV_TYPE_DOMAIN_BAKCTRL      0x00000010
59 #define SV_TYPE_TIME_SOURCE         0x00000020
60 #define SV_TYPE_AFP                 0x00000040
61 #define SV_TYPE_NOVELL              0x00000080
62 #define SV_TYPE_DOMAIN_MEMBER       0x00000100
63 #define SV_TYPE_PRINTQ_SERVER       0x00000200
64 #define SV_TYPE_DIALIN_SERVER       0x00000400
65 #define SV_TYPE_XENIX_SERVER        0x00000800
66 #define SV_TYPE_SERVER_UNIX         SV_TYPE_XENIX_SERVER
67 #define SV_TYPE_NT                  0x00001000
68 #define SV_TYPE_WFW                 0x00002000
69 #define SV_TYPE_SERVER_MFPN         0x00004000
70 #define SV_TYPE_SERVER_NT           0x00008000
71 #define SV_TYPE_POTENTIAL_BROWSER   0x00010000
72 #define SV_TYPE_BACKUP_BROWSER      0x00020000
73 #define SV_TYPE_MASTER_BROWSER      0x00040000
74 #define SV_TYPE_DOMAIN_MASTER       0x00080000
75 #define SV_TYPE_SERVER_OSF          0x00100000
76 #define SV_TYPE_SERVER_VMS          0x00200000
77 #define SV_TYPE_WINDOWS             0x00400000  /* Windows95 and above */
78 #define SV_TYPE_DFS                 0x00800000  /* Root of a DFS tree */
79 #define SV_TYPE_CLUSTER_NT          0x01000000  /* NT Cluster */
80 #define SV_TYPE_TERMINALSERVER      0x02000000  /* Terminal Server(Hydra) */
81 #define SV_TYPE_CLUSTER_VS_NT       0x04000000  /* NT Cluster Virtual Server Name */
82 #define SV_TYPE_DCE                 0x10000000  /* IBM DSS (Directory and Security Services) or equivalent */
83 #define SV_TYPE_ALTERNATE_XPORT     0x20000000  /* return list for alternate transport */
84 #define SV_TYPE_LOCAL_LIST_ONLY     0x40000000  /* Return local list only */
85 #define SV_TYPE_DOMAIN_ENUM         0x80000000
86 #define SV_TYPE_ALL                 0xFFFFFFFF  /* handy for NetServerEnum2 */
87 //
88 //      Values of svX_hidden field. X = 2 or 3.
89 //
90 #define SV_HIDDEN       1
91 #define SV_VISIBLE      0
92
93 NET_API_STATUS NetrConnectionEnum(
94     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
95     /* [unique][string][in] */ WCHAR *Qualifier,
96     /* [out][in] */ LPCONNECT_ENUM_STRUCT InfoStruct,
97     /* [in] */ DWORD PreferedMaximumLength,
98     /* [out] */ DWORD *TotalEntries,
99     /* [unique][out][in] */ DWORD *ResumeHandle)
100 {
101     return ERROR_NOT_SUPPORTED;
102 }
103
104 NET_API_STATUS NetrFileEnum(
105     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
106     /* [unique][string][in] */ WCHAR *BasePath,
107     /* [unique][string][in] */ WCHAR *UserName,
108     /* [out][in] */ PFILE_ENUM_STRUCT InfoStruct,
109     /* [in] */ DWORD PreferedMaximumLength,
110     /* [out] */ DWORD *TotalEntries,
111     /* [unique][out][in] */ DWORD *ResumeHandle)
112 {
113     return ERROR_NOT_SUPPORTED;
114 }
115
116 NET_API_STATUS NetrFileGetInfo(
117     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
118     /* [in] */ DWORD FileId,
119     /* [in] */ DWORD Level,
120     /* [switch_is][out] */ LPFILE_INFO InfoStruct)
121 {
122     return ERROR_NOT_SUPPORTED;
123 }
124
125 NET_API_STATUS NetrFileClose(
126     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
127     /* [in] */ DWORD FileId)
128 {
129     return ERROR_NOT_SUPPORTED;
130 }
131
132 NET_API_STATUS NetrSessionEnum(
133     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
134     /* [unique][string][in] */ WCHAR *ClientName,
135     /* [unique][string][in] */ WCHAR *UserName,
136     /* [out][in] */ PSESSION_ENUM_STRUCT InfoStruct,
137     /* [in] */ DWORD PreferedMaximumLength,
138     /* [out] */ DWORD *TotalEntries,
139     /* [unique][out][in] */ DWORD *ResumeHandle)
140 {
141     return ERROR_NOT_SUPPORTED;
142 }
143
144 NET_API_STATUS NetrSessionDel(
145     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
146     /* [unique][string][in] */ WCHAR *ClientName,
147     /* [unique][string][in] */ WCHAR *UserName)
148 {
149     return ERROR_NOT_SUPPORTED;
150 }
151
152 NET_API_STATUS NetrShareAdd(
153     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
154     /* [in] */ DWORD Level,
155     /* [switch_is][in] */ LPSHARE_INFO InfoStruct,
156     /* [unique][out][in] */ DWORD *ParmErr)
157 {
158     return ERROR_NOT_SUPPORTED;
159 }
160
161 static wchar_t *
162 NetrIntGenerateShareRemark(cm_scache_t *scp, cm_fid_t *fidp)
163 {
164     wchar_t remark[1536], *s, *wcellname, *wmp;
165     HRESULT hr;
166     cm_cell_t *cellp;
167     afs_int32 b;
168
169     cellp = cm_FindCellByID(fidp->cell, CM_FLAG_NOPROBE);
170
171     if (cellp)
172         wcellname = cm_FsStringToClientStringAlloc(cellp->name, -1, NULL);
173     else
174         wcellname = L"";
175
176     if (scp) {
177         switch (scp->fileType) {
178         case 1:
179             hr = StringCchPrintfW( remark,
180                                    sizeof(remark)/sizeof(remark[0]),
181                                    L"AFS File (%s:%u.%u.%u)",
182                                    wcellname,
183                                    scp->fid.volume,
184                                    scp->fid.vnode, scp->fid.unique);
185             if (hr == S_OK)
186                 s = wcsdup(remark);
187             else
188                 s = wcsdup(L"AFS File");
189             break;
190         case 2:
191             hr = StringCchPrintfW( remark,
192                                    sizeof(remark)/sizeof(remark[0]),
193                                    L"AFS Directory (%s:%u.%u.%u)",
194                                    wcellname,
195                                    scp->fid.volume,
196                                    scp->fid.vnode, scp->fid.unique);
197             if (hr == S_OK)
198                 s = wcsdup(remark);
199             else
200                 s = wcsdup(L"AFS Directory");
201             break;
202         case 3:
203             wmp = cm_FsStringToClientStringAlloc(scp->mountPointStringp, -1, NULL);
204             hr = StringCchPrintfW( remark,
205                                    sizeof(remark)/sizeof(remark[0]),
206                                    L"AFS Symlink to %s",
207                                    wmp ? wmp : L"");
208             if (hr == S_OK)
209                 s = wcsdup(remark);
210             else
211                 s = wcsdup(L"AFS Symlink");
212             if (wmp)
213                 free(wmp);
214             break;
215         case 4:
216             b = (strchr(scp->mountPointStringp, ':') != NULL);
217             wmp = cm_FsStringToClientStringAlloc(scp->mountPointStringp, -1, NULL);
218             hr = StringCchPrintfW( remark,
219                                    sizeof(remark)/sizeof(remark[0]),
220                                    L"AFS MountPoint to %s%s%s%s",
221                                    wmp ? wmp : L"",
222                                    b ? L"" : L" (",
223                                    b ? L"" : wcellname,
224                                    b ? L"" : L")");
225             if (hr == S_OK)
226                 s = wcsdup(remark);
227             else
228                 s = wcsdup(L"AFS MountPoint");
229             if (wmp)
230                 free(wmp);
231             break;
232         case 5:
233             wmp = cm_FsStringToClientStringAlloc(scp->mountPointStringp, -1, NULL);
234             hr = StringCchPrintfW( remark,
235                                    sizeof(remark)/sizeof(remark[0]),
236                                    L"AFS Dfslink to %s",
237                                    wmp ? wmp : L"");
238             if (hr == S_OK)
239                 s = wcsdup(remark);
240             else
241                 s = wcsdup(L"AFS DfsLink");
242             if (wmp)
243                 free(wmp);
244             break;
245         default:
246             hr = StringCchPrintfW( remark,
247                                    sizeof(remark)/sizeof(remark[0]),
248                                    L"AFS Object (%s:%u.%u.%u)",
249                                    wcellname,
250                                    scp->fid.volume,
251                                    scp->fid.vnode, scp->fid.unique);
252             if (hr == S_OK)
253                 s = wcsdup(remark);
254             else
255                 s = wcsdup(L"AFS Object");
256         }
257     } else {
258         if (fidp->vnode & 1) {
259             hr = StringCchPrintfW( remark,
260                                    sizeof(remark)/sizeof(remark[0]),
261                                    L"AFS Directory (%s:%u.%u.%u)",
262                                    wcellname,
263                                    fidp->volume,
264                                    fidp->vnode, fidp->unique);
265             if (hr == S_OK)
266                 s = wcsdup(remark);
267             else
268                 s = wcsdup(L"AFS Directory");
269         } else {
270             hr = StringCchPrintfW( remark,
271                                    sizeof(remark)/sizeof(remark[0]),
272                                    L"AFS Object (%s:%u.%u.%u)",
273                                    wcellname,
274                                    fidp->volume,
275                                    fidp->vnode, fidp->unique);
276             if (hr == S_OK)
277                 s = wcsdup(remark);
278             else
279                 s = wcsdup(L"AFS Object");
280         }
281     }
282     if (cellp && wcellname)
283         free(wcellname);
284     return s;
285 }
286
287 static wchar_t *
288 NetrIntGenerateSharePath(wchar_t *ServerName, cm_fid_t *fidp)
289 {
290     wchar_t remark[1536], *s, *wcellname;
291     HRESULT hr;
292     cm_cell_t *cellp;
293
294     cellp = cm_FindCellByID(fidp->cell, CM_FLAG_NOPROBE);
295
296     if (cellp)
297         wcellname = cm_FsStringToClientStringAlloc(cellp->name, -1, NULL);
298     else
299         wcellname = L"";
300
301     hr = StringCchPrintfW( remark,
302                            sizeof(remark)/sizeof(remark[0]),
303                            L"\\%s\\%s\\%u.%u.%u",
304                            ServerName, wcellname,
305                            fidp->volume,
306                            fidp->vnode, fidp->unique);
307     if (hr == S_OK)
308         s = wcsdup(remark);
309     else
310         s = wcsdup(L"");
311
312     if (cellp && wcellname)
313         free(wcellname);
314     return s;
315 }
316
317 typedef struct netr_share_enum {
318     osi_queue_t   q;
319     time_t        cleanup_time;
320     DWORD         handle;
321     cm_direnum_t *direnump;
322 } netr_share_enum_t;
323
324 static osi_queue_t * shareEnumQ = NULL;
325 static osi_mutex_t   shareEnum_mx;
326 static DWORD         shareEnum_next_handle=1;
327
328 void
329 RPC_SRVSVC_Init(void)
330 {
331     lock_InitializeMutex(&shareEnum_mx, "NetrShareEnum", 0);
332     shareEnumQ = NULL;
333 #if _MSC_VER < 1500
334     srand((unsigned) time( NULL ));
335     shareEnum_next_handle = rand();
336 #else
337     rand_s(&shareEnum_next_handle);
338 #endif
339 }
340
341 void
342 RPC_SRVSVC_Shutdown(void)
343 {
344     netr_share_enum_t *enump;
345
346     lock_ObtainMutex(&shareEnum_mx);
347     while (shareEnumQ) {
348         enump = (netr_share_enum_t *)shareEnumQ;
349         cm_BPlusDirFreeEnumeration(enump->direnump);
350         osi_QRemove(&shareEnumQ, (osi_queue_t *)enump);
351         free(enump);
352     }
353     lock_FinalizeMutex(&shareEnum_mx);
354 }
355
356 static void
357 RPC_SRVSVC_ShareEnumAgeCheck(void) {
358     netr_share_enum_t *enump, *enumnp;
359     time_t            now;
360
361     lock_ObtainMutex(&shareEnum_mx);
362     now = time(NULL);
363     for (enump = (netr_share_enum_t *)shareEnumQ;
364          enump; enump = enumnp) {
365         enumnp = (netr_share_enum_t *) osi_QNext(&(enump->q));
366         if (now > enump->cleanup_time)
367             osi_QRemove(&shareEnumQ, (osi_queue_t *)enump);
368     }
369     lock_ReleaseMutex(&shareEnum_mx);
370 }
371
372 static cm_direnum_t *
373 RPC_SRVSVC_ShareEnumFind(DWORD ResumeHandle) {
374     netr_share_enum_t *enump;
375
376     lock_ObtainMutex(&shareEnum_mx);
377     for (enump = (netr_share_enum_t *)shareEnumQ;
378          enump;
379          enump = (netr_share_enum_t *) osi_QNext(&enump->q)) {
380         if (ResumeHandle == enump->handle)
381             break;
382     }
383     lock_ReleaseMutex(&shareEnum_mx);
384
385     return enump ? enump->direnump : NULL;
386 }
387
388 static DWORD
389 RPC_SRVSVC_ShareEnumSave(cm_direnum_t *direnump) {
390     netr_share_enum_t *enump = (netr_share_enum_t *)malloc(sizeof(netr_share_enum_t));
391
392     if (enump == NULL)
393         return 0xFFFFFFFF;
394
395     lock_ObtainMutex(&shareEnum_mx);
396     enump->cleanup_time = time(NULL) + 300;
397     enump->handle = shareEnum_next_handle++;
398     if (shareEnum_next_handle == 0xFFFFFFFF)
399         shareEnum_next_handle = 1;
400     enump->direnump = direnump;
401     osi_QAdd(&shareEnumQ, (osi_queue_t *)enump);
402     lock_ReleaseMutex(&shareEnum_mx);
403
404     return enump->handle;
405 }
406
407 static void
408 RPC_SRVSVC_ShareEnumRemove(cm_direnum_t *direnump) {
409     netr_share_enum_t *enump;
410
411     lock_ObtainMutex(&shareEnum_mx);
412     for (enump = (netr_share_enum_t *)shareEnumQ;
413          enump;
414          enump = (netr_share_enum_t *) osi_QNext(&enump->q)) {
415         if (direnump == enump->direnump) {
416             osi_QRemove(&shareEnumQ, (osi_queue_t *)enump);
417             break;
418         }
419     }
420     lock_ReleaseMutex(&shareEnum_mx);
421 }
422
423 NET_API_STATUS NetrShareEnum(
424     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
425     /* [out][in] */ LPSHARE_ENUM_STRUCT InfoStruct,
426     /* [in] */ DWORD PreferedMaximumLength,
427     /* [out] */ DWORD *TotalEntries,
428     /* [unique][out][in] */ DWORD *ResumeHandle)
429 {
430     cm_direnum_t *enump = NULL;
431     cm_direnum_entry_t * entryp = NULL;
432     cm_scache_t * dscp = cm_data.rootSCachep;
433     cm_user_t *userp = MSRPC_GetCmUser();
434     cm_req_t      req;
435     int           stopnow = 0;
436     afs_uint32    count = 0;
437     afs_uint32    code;
438     afs_uint32    old_enum = 0;
439     size_t        space_limited = 0;
440     size_t        space_available = 0;
441     afs_uint32    first_entry = 1;
442
443     cm_InitReq(&req);
444
445     RPC_SRVSVC_ShareEnumAgeCheck();
446
447     /* We only support one server name so ignore 'ServerName'. */
448
449     /* Test for unsupported level early */
450     switch (InfoStruct->Level) {
451     case 2:
452     case 1:
453     case 0:
454         break;
455     default:
456         return ERROR_INVALID_LEVEL;
457     }
458
459     if (ResumeHandle && *ResumeHandle == 0xFFFFFFFF) {
460         /* No More Entries */
461         InfoStruct->ShareInfo.Level0->EntriesRead = 0;
462         return ERROR_NO_MORE_FILES;
463     }
464
465     /* get the directory size */
466     cm_HoldSCache(dscp);
467     lock_ObtainWrite(&dscp->rw);
468     code = cm_SyncOp(dscp, NULL, userp, &req, PRSFS_LOOKUP,
469                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
470     if (code) {
471         lock_ReleaseWrite(&dscp->rw);
472         cm_ReleaseSCache(dscp);
473         osi_Log1(afsd_logp, "NetShareEnum cm_SyncOp failure code=0x%x", code);
474         return ERROR_BUSY;
475     }
476
477     cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
478     lock_ReleaseWrite(&dscp->rw);
479
480     if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
481         cm_ReleaseSCache(dscp);
482         osi_Log1(afsd_logp, "NetShareEnum Not a Directory dscp=0x%p", dscp);
483         return ERROR_DIRECTORY;
484     }
485
486     /*
487      * If there is no enumeration handle, then this is a new query
488      * and we must perform an enumeration for the specified object
489      */
490     if (ResumeHandle == NULL || *ResumeHandle == 0) {
491         cm_dirOp_t    dirop;
492
493         code = cm_BeginDirOp(dscp, userp, &req, CM_DIRLOCK_READ, &dirop);
494         if (code == 0) {
495             code = cm_BPlusDirEnumerate(dscp, userp, &req, TRUE, NULL, TRUE, &enump);
496             if (code) {
497                 osi_Log1(afsd_logp, "NetShareEnum cm_BPlusDirEnumerate failure code=0x%x",
498                           code);
499             }
500             cm_EndDirOp(&dirop);
501         } else {
502             osi_Log1(afsd_logp, "NetShareEnum cm_BeginDirOp failure code=0x%x",
503                       code);
504         }
505         old_enum = 0;
506     } else {
507         enump = RPC_SRVSVC_ShareEnumFind(*ResumeHandle);
508         old_enum = 1;
509     }
510
511     if (enump == NULL) {
512         cm_ReleaseSCache(dscp);
513         osi_Log0(afsd_logp, "NetShareEnum No Enumeration Present");
514         *TotalEntries = 0;
515         return (code ? ERROR_BUSY : ERROR_SUCCESS);
516     }
517
518     /*
519      * Do not exceed PreferredMaximumLength in any response.
520      * 0xFFFFFFFF means no limit.
521      *
522      * *TotalEntries is a hint of the total entries in the
523      * enumeration.  It does not have to be exact.  It is
524      * the same for each response in an enum.
525      *
526      * If *ResumeHandle == 0, this is an initial call
527      *
528      * The algorithm will be to enumerate the list of share
529      * names based upon the contents of the root.afs root
530      * directory.  We will ignore SMB submount names.
531      * The enumeration will be valid for five minutes.  If
532      * the enumeration is not destroyed within that time period
533      * it will be automatically garbage collected.
534      */
535
536     /*
537      * How much space do we need and do we have that much room?
538      *
539      * If a preferred maximum length is specified, then we must
540      * manage the number of bytes we return in order to restrict
541      * it to a value smaller than then the preferred.  This includes
542      * not only the InfoStruct but also the allocated SHARE_INFO
543      * buffer and the various C strings.  We are not permitted to
544      * send incomplete values so we will send a value that is close.
545      */
546     if (PreferedMaximumLength != 0xFFFFFFFF) {
547         space_limited = 1;
548         space_available =  PreferedMaximumLength;
549     }
550
551     switch (InfoStruct->Level) {
552     case 2:
553         if (space_limited)
554             space_available -= sizeof(InfoStruct->ShareInfo.Level2);
555         InfoStruct->ShareInfo.Level2->Buffer = calloc((enump->count - enump->next), sizeof(SHARE_INFO_2));
556         break;
557     case 1:
558         if (space_limited)
559             space_available -= sizeof(InfoStruct->ShareInfo.Level1);
560         InfoStruct->ShareInfo.Level1->Buffer = calloc((enump->count - enump->next), sizeof(SHARE_INFO_1));
561         break;
562     case 0:
563         if (space_limited)
564             space_available -= sizeof(InfoStruct->ShareInfo.Level0);
565         InfoStruct->ShareInfo.Level0->Buffer = calloc((enump->count - enump->next), sizeof(SHARE_INFO_0));
566         break;
567     }
568
569     if (InfoStruct->ShareInfo.Level0->Buffer == NULL) {
570         cm_ReleaseSCache(dscp);
571         cm_BPlusDirFreeEnumeration(enump);
572         osi_Log0(afsd_logp, "NetShareEnum No Enumeration Present");
573         return ERROR_NOT_ENOUGH_MEMORY;
574     }
575
576     while (!stopnow) {
577         cm_scache_t *scp;
578
579         if (space_limited)
580             code = cm_BPlusDirPeekNextEnumEntry(enump, &entryp);
581         else
582             code = cm_BPlusDirNextEnumEntry(enump, &entryp);
583         if (code != 0 && code != CM_ERROR_STOPNOW || entryp == NULL)
584             break;
585
586         stopnow = (code == CM_ERROR_STOPNOW);
587
588         if ( !wcscmp(L".", entryp->name) || !wcscmp(L"..", entryp->name) ) {
589             osi_Log0(afsd_logp, "NetShareEnum skipping . or ..");
590             if (space_limited)
591                 cm_BPlusDirNextEnumEntry(enump, &entryp);
592             continue;
593         }
594
595         cm_GetSCache(&entryp->fid, &scp, userp, &req);
596
597         switch (InfoStruct->Level) {
598         case 2:
599             /* for share level security */
600             InfoStruct->ShareInfo.Level2->Buffer[count].shi2_permissions = 0;
601             InfoStruct->ShareInfo.Level2->Buffer[count].shi2_max_uses = -1;
602             InfoStruct->ShareInfo.Level2->Buffer[count].shi2_current_uses = 0;
603             InfoStruct->ShareInfo.Level2->Buffer[count].shi2_path =
604                 NetrIntGenerateSharePath(ServerName, &entryp->fid);
605             /* must be the empty string */
606             InfoStruct->ShareInfo.Level2->Buffer[count].shi2_passwd = wcsdup(L"");
607
608             InfoStruct->ShareInfo.Level2->Buffer[count].shi2_type = STYPE_DISKTREE;
609             InfoStruct->ShareInfo.Level2->Buffer[count].shi2_remark =
610                 NetrIntGenerateShareRemark(scp, &entryp->fid);
611             InfoStruct->ShareInfo.Level2->Buffer[count].shi2_netname = wcsdup(entryp->name);
612             break;
613         case 1:
614             InfoStruct->ShareInfo.Level1->Buffer[count].shi1_type = STYPE_DISKTREE;
615             InfoStruct->ShareInfo.Level1->Buffer[count].shi1_remark =
616                 NetrIntGenerateShareRemark(scp, &entryp->fid);
617             InfoStruct->ShareInfo.Level1->Buffer[count].shi1_netname = wcsdup(entryp->name);
618             break;
619         case 0:
620             InfoStruct->ShareInfo.Level0->Buffer[count].shi0_netname = wcsdup(entryp->name);
621         }
622
623         if (scp)
624             cm_ReleaseSCache(scp);
625
626         if (space_limited) {
627             size_t space_used;
628             /*
629              * If space is limited, we need to determine if there is room
630              * for the next entry but always send at least one.
631              */
632             switch (InfoStruct->Level) {
633             case 2:
634                 space_used = sizeof(InfoStruct->ShareInfo.Level2->Buffer[count]) +
635                     (wcslen(InfoStruct->ShareInfo.Level2->Buffer[count].shi2_path) + 1) * sizeof(wchar_t) +
636                     sizeof(wchar_t) +  /* passwd */
637                     (wcslen(InfoStruct->ShareInfo.Level2->Buffer[count].shi2_remark) + 1) * sizeof(wchar_t) +
638                     (wcslen(InfoStruct->ShareInfo.Level2->Buffer[count].shi2_netname) + 1) * sizeof(wchar_t);
639                 break;
640             case 1:
641                 space_used = sizeof(InfoStruct->ShareInfo.Level1->Buffer[count]) +
642                     (wcslen(InfoStruct->ShareInfo.Level1->Buffer[count].shi1_remark) + 1) * sizeof(wchar_t) +
643                     (wcslen(InfoStruct->ShareInfo.Level1->Buffer[count].shi1_netname) + 1) * sizeof(wchar_t);
644                 break;
645             case 0:
646                 space_used = sizeof(InfoStruct->ShareInfo.Level0->Buffer[count]) +
647                     (wcslen(InfoStruct->ShareInfo.Level0->Buffer[count].shi0_netname) + 1) * sizeof(wchar_t);
648                 break;
649             }
650
651             if (!first_entry && space_used > space_available)
652                 break;
653
654             /* Now consume the entry */
655             cm_BPlusDirNextEnumEntry(enump, &entryp);
656             space_available -= space_used;
657         }
658         count++;
659         first_entry = 0;
660     }
661     InfoStruct->ShareInfo.Level0->EntriesRead = count;
662     *TotalEntries = enump->count;
663     if (dscp)
664         cm_ReleaseSCache(dscp);
665
666     if (code || enump->next == enump->count || ResumeHandle == NULL) {
667         if (old_enum)
668             RPC_SRVSVC_ShareEnumRemove(enump);
669         cm_BPlusDirFreeEnumeration(enump);
670         if (ResumeHandle)
671             *ResumeHandle = 0xFFFFFFFF;
672         return (code || enump->next == enump->count) ? 0 : ERROR_MORE_DATA;
673     } else {
674         *ResumeHandle = RPC_SRVSVC_ShareEnumSave(enump);
675         return ERROR_MORE_DATA;
676     }
677 }
678
679 NET_API_STATUS NetrShareGetInfo(
680     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
681     /* [string][in] */ WCHAR *NetName,
682     /* [in] */ DWORD Level,
683     /* [switch_is][out] */ LPSHARE_INFO InfoStruct)
684 {
685     cm_scache_t * dscp = cm_data.rootSCachep;
686     cm_scache_t * scp = NULL;
687     cm_user_t *userp = MSRPC_GetCmUser();
688     cm_req_t      req;
689     afs_uint32    code = 0;
690     NET_API_STATUS status = 0;
691     HKEY parmKey;
692     /* make room for '/@vol:' + mountchar + NULL terminator*/
693     clientchar_t pathstr[CELL_MAXNAMELEN + VL_MAXNAMELEN + 1 + CM_PREFIX_VOL_CCH];
694     DWORD  cblen;
695
696     cm_InitReq(&req);
697
698     /* Allocate the memory for the response */
699     switch (Level) {
700     case 2:
701         InfoStruct->ShareInfo2 = calloc(1, sizeof(SHARE_INFO_2));
702         break;
703     case 1:
704         InfoStruct->ShareInfo1 = calloc(1, sizeof(SHARE_INFO_1));
705         break;
706     case 0:
707         InfoStruct->ShareInfo0 = calloc(1, sizeof(SHARE_INFO_0));
708         break;
709     }
710
711     if (InfoStruct->ShareInfo0 == NULL) {
712         return ERROR_NOT_ENOUGH_MEMORY;
713     }
714
715     /*
716      * NetName will be:
717      *  1.a an entry in the root.afs volume root directory
718      *  1.b an entry in the Freelance volume root directory
719      *  2. A volume reference: <cell><type><volume>
720      *  3. an SMB Submount name
721      *  4. a cell name that we do not yet have an entry
722      *     for in the Freelance volume root directory
723      */
724
725     /*
726      * To obtain the needed information for the response we
727      * need to obtain the cm_scache_t entry.  First check to
728      * see if the NetName is a volume reference, then check
729      * if the NetName is an entry in the root volume root
730      * directory, finally we can check the SMB Submounts.
731      * Volume references and SMB submounts are not advertised
732      * as part of the Share enumerations but we should provide
733      * Share info for them nevertheless.  Same for the secret
734      * "all" share.
735      */
736
737     /* Check for volume references
738      *
739      * They look like <cell>{%,#}<volume>
740      */
741     if (cm_ClientStrChr(NetName, '%') != NULL ||
742         cm_ClientStrChr(NetName, '#') != NULL)
743     {
744         osi_Log1(afsd_logp, "NetrShareGetInfo found volume reference [%S]",
745                  osi_LogSaveClientString(afsd_logp, NetName));
746
747         cm_ClientStrPrintfN(pathstr, lengthof(pathstr),
748                             _C(CM_PREFIX_VOL) _C("%s"), NetName);
749         code = cm_Lookup(dscp, pathstr, 0, userp, &req, &scp);
750     } else if (cm_ClientStrCmpI(NetName, L"ALL") == 0) {
751         DWORD allSubmount = 1;
752
753         /* if allSubmounts == 0, only return the //mountRoot/all share
754          * if in fact it has been been created in the subMounts table.
755          * This is to allow sites that want to restrict access to the
756          * world to do so.
757          */
758         code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
759                              0, KEY_QUERY_VALUE, &parmKey);
760         if (code == ERROR_SUCCESS) {
761             cblen = sizeof(allSubmount);
762             code = RegQueryValueEx(parmKey, "AllSubmount", NULL, NULL,
763                                     (BYTE *) &allSubmount, &cblen);
764             if (code != ERROR_SUCCESS) {
765                 allSubmount = 1;
766             }
767             RegCloseKey (parmKey);
768         }
769
770         if (allSubmount) {
771             scp = dscp;
772             cm_HoldSCache(scp);
773         }
774     } else {
775         /*
776          * Could be a Submount, a directory entry, or a cell name we
777          * have yet to create an entry for.
778          */
779
780         /* Try a directory entry first */
781         code = cm_Lookup(dscp, NetName, CM_FLAG_NOMOUNTCHASE,
782                           userp, &req, &scp);
783         if (code && code != CM_ERROR_NOACCESS)
784             code = cm_Lookup(dscp, NetName, CM_FLAG_CASEFOLD | CM_FLAG_NOMOUNTCHASE,
785                               userp, &req, &scp);
786
787         if (scp == NULL && code != CM_ERROR_NOACCESS) {  /* Try a submount */
788             code = RegOpenKeyExW(HKEY_LOCAL_MACHINE,  L"Software\\OpenAFS\\Client\\Submounts",
789                                   0, KEY_QUERY_VALUE, &parmKey);
790             if (code == ERROR_SUCCESS) {
791                 cblen = sizeof(pathstr);
792                 code = RegQueryValueExW(parmKey, NetName, NULL, NULL,
793                                          (BYTE *) pathstr, &cblen);
794                 if (code != ERROR_SUCCESS)
795                     cblen = 0;
796                 RegCloseKey (parmKey);
797             } else {
798                 cblen = 0;
799             }
800
801             if (cblen) {
802                 code = cm_NameI(dscp, pathstr, CM_FLAG_FOLLOW, userp, NULL, &req, &scp);
803                 if (code && code != CM_ERROR_NOACCESS)
804                     code = cm_NameI(dscp, pathstr, CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
805                                       userp, NULL, &req, &scp);
806             }
807         }
808     }
809
810     if (scp) {
811         switch (Level) {
812         case 2:
813             /* for share level security */
814             InfoStruct->ShareInfo2->shi2_permissions = 0;
815             InfoStruct->ShareInfo2->shi2_max_uses = -1;
816             InfoStruct->ShareInfo2->shi2_current_uses = 0;
817             InfoStruct->ShareInfo2->shi2_path =
818                 NetrIntGenerateSharePath(ServerName, &scp->fid);
819             /* must be the empty string */
820             InfoStruct->ShareInfo2->shi2_passwd = wcsdup(L"");
821             /* fall-through */
822         case 1:
823             InfoStruct->ShareInfo1->shi1_type = STYPE_DISKTREE;
824             InfoStruct->ShareInfo1->shi1_remark =
825                 NetrIntGenerateShareRemark(scp, &scp->fid);
826             /* fall-through */
827         case 0:
828             /* Canonicalized version of NetName parameter */
829             InfoStruct->ShareInfo0->shi0_netname = wcsdup(NetName);
830             break;
831         case 501:
832         case 502:
833         case 503:
834         case 1004:
835         case 1005:
836         case 1006:
837         default:
838             status = ERROR_INVALID_LEVEL;
839         }
840         cm_ReleaseSCache(scp);
841     } else {
842         /*
843          * The requested object does not exist.
844          * Return the correct NERR or Win32 Error.
845          */
846         smb_MapWin32Error(code, &status);
847         switch (status) {
848         case ERROR_FILE_NOT_FOUND:
849         case ERROR_PATH_NOT_FOUND:
850         case ERROR_INVALID_NAME:
851         case ERROR_BAD_NETPATH:
852             status = NERR_NetNameNotFound;
853             break;
854         }
855     }
856     return status;
857 }
858
859 NET_API_STATUS NetrShareSetInfo(
860     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
861     /* [string][in] */ WCHAR *NetName,
862     /* [in] */ DWORD Level,
863     /* [switch_is][in] */ LPSHARE_INFO ShareInfo,
864     /* [unique][out][in] */ DWORD *ParmErr)
865 {
866     return ERROR_NOT_SUPPORTED;
867 }
868
869 NET_API_STATUS NetrShareDel(
870     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
871     /* [string][in] */ WCHAR *NetName,
872     /* [in] */ DWORD Reserved)
873 {
874     return ERROR_NOT_SUPPORTED;
875 }
876
877 NET_API_STATUS NetrShareDelSticky(
878     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
879     /* [string][in] */ WCHAR *NetName,
880     /* [in] */ DWORD Reserved)
881 {
882     return ERROR_NOT_SUPPORTED;
883 }
884
885 NET_API_STATUS NetrShareCheck(
886     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
887     /* [string][in] */ WCHAR *Device,
888     /* [out] */ DWORD *Type)
889 {
890     return ERROR_NOT_SUPPORTED;
891 }
892
893 NET_API_STATUS NetrServerGetInfo(
894     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
895     /* [in] */ DWORD Level,
896     /* [switch_is][out] */ LPSERVER_INFO InfoStruct)
897 {
898     /*
899     * How much space do we need and do we have that much room?
900     * For now, just assume we can return everything in one shot
901     * because the reality is that in this function call we do
902     * not know the max size of the RPC response.
903     */
904     switch (Level) {
905     case 103:
906         InfoStruct->ServerInfo103 = calloc(1, sizeof(SERVER_INFO_103));
907         break;
908     case 102:
909         InfoStruct->ServerInfo102 = calloc(1, sizeof(SERVER_INFO_102));
910         break;
911     case 101:
912         InfoStruct->ServerInfo101 = calloc(1, sizeof(SERVER_INFO_101));
913         break;
914     case 100:
915         InfoStruct->ServerInfo100 = calloc(1, sizeof(SERVER_INFO_100));
916         break;
917     }
918
919     if (InfoStruct->ServerInfo100 == NULL) {
920         return ERROR_NOT_ENOUGH_MEMORY;
921     }
922
923     switch (Level) {
924     case 103:
925         InfoStruct->ServerInfo103->sv103_capabilities = 0;
926         /* fall-through */
927     case 102:
928         InfoStruct->ServerInfo102->sv102_users = 0xFFFFFFFF;
929         InfoStruct->ServerInfo102->sv102_disc = SV_NODISC;
930         InfoStruct->ServerInfo102->sv102_hidden = SV_HIDDEN;
931         InfoStruct->ServerInfo102->sv102_announce = 65535;
932         InfoStruct->ServerInfo102->sv102_anndelta = 0;
933         InfoStruct->ServerInfo102->sv102_licenses = 0;
934         InfoStruct->ServerInfo102->sv102_userpath = wcsdup(L"C:\\");
935         /* fall-through */
936     case 101:
937         InfoStruct->ServerInfo101->sv101_version_major = AFSPRODUCT_VERSION_MAJOR;
938         InfoStruct->ServerInfo101->sv101_version_minor = AFSPRODUCT_VERSION_MINOR;
939         InfoStruct->ServerInfo101->sv101_type = SV_TYPE_SERVER_UNIX;
940         InfoStruct->ServerInfo101->sv101_comment = wcsdup(wAFSVersion);
941         /* fall-through */
942     case 100:
943         InfoStruct->ServerInfo100->sv100_platform_id = SV_PLATFORM_ID_AFS;
944         /* The Netbios Name */
945         InfoStruct->ServerInfo100->sv100_name = wcsdup(ServerName);
946         return 0;
947     case 502:
948     case 503:
949     case 599:
950     case 1005:
951     case 1107:
952     case 1010:
953     case 1016:
954     case 1017:
955     case 1018:
956     case 1501:
957     case 1502:
958     case 1503:
959     case 1506:
960     case 1510:
961     case 1511:
962     case 1512:
963     case 1513:
964     case 1514:
965     case 1515:
966     case 1516:
967     case 1518:
968     case 1523:
969     case 1528:
970     case 1529:
971     case 1530:
972     case 1533:
973     case 1534:
974     case 1535:
975     case 1536:
976     case 1538:
977     case 1539:
978     case 1540:
979     case 1541:
980     case 1542:
981     case 1543:
982     case 1544:
983     case 1545:
984     case 1546:
985     case 1547:
986     case 1548:
987     case 1549:
988     case 1550:
989     case 1552:
990     case 1553:
991     case 1554:
992     case 1555:
993     case 1556:
994     default:
995         return ERROR_INVALID_LEVEL;
996     }
997     return 0;
998 }
999
1000 NET_API_STATUS NetrServerSetInfo(
1001     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1002     /* [in] */ DWORD Level,
1003     /* [switch_is][in] */ LPSERVER_INFO ServerInfo,
1004     /* [unique][out][in] */ DWORD *ParmErr)
1005 {
1006     return ERROR_NOT_SUPPORTED;
1007 }
1008
1009 NET_API_STATUS NetrServerDiskEnum(
1010     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1011     /* [in] */ DWORD Level,
1012     /* [out][in] */ DISK_ENUM_CONTAINER *DiskInfoStruct,
1013     /* [in] */ DWORD PreferedMaximumLength,
1014     /* [out] */ DWORD *TotalEntries,
1015     /* [unique][out][in] */ DWORD *ResumeHandle)
1016 {
1017     return ERROR_NOT_SUPPORTED;
1018 }
1019
1020 NET_API_STATUS NetrServerStatisticsGet(
1021     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1022     /* [unique][string][in] */ WCHAR *Service,
1023     /* [in] */ DWORD Level,
1024     /* [in] */ DWORD Options,
1025     /* [out] */ LPSTAT_SERVER_0 *InfoStruct)
1026 {
1027     return ERROR_NOT_SUPPORTED;
1028 }
1029
1030 NET_API_STATUS NetrServerTransportAdd(
1031     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1032     /* [in] */ DWORD Level,
1033     /* [in] */ LPSERVER_TRANSPORT_INFO_0 Buffer)
1034 {
1035     return ERROR_NOT_SUPPORTED;
1036 }
1037
1038 NET_API_STATUS NetrServerTransportEnum(
1039     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1040     /* [out][in] */ LPSERVER_XPORT_ENUM_STRUCT InfoStruct,
1041     /* [in] */ DWORD PreferedMaximumLength,
1042     /* [out] */ DWORD *TotalEntries,
1043     /* [unique][out][in] */ DWORD *ResumeHandle)
1044 {
1045     return ERROR_NOT_SUPPORTED;
1046 }
1047
1048 NET_API_STATUS NetrServerTransportDel(
1049     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1050     /* [in] */ DWORD Level,
1051     /* [in] */ LPSERVER_TRANSPORT_INFO_0 Buffer)
1052 {
1053     return ERROR_NOT_SUPPORTED;
1054 }
1055
1056 NET_API_STATUS NetrRemoteTOD(
1057     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1058     /* [out] */ LPTIME_OF_DAY_INFO *BufferPtr)
1059 {
1060     return ERROR_NOT_SUPPORTED;
1061 }
1062
1063 NET_API_STATUS NetprPathType(
1064     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1065     /* [string][in] */ WCHAR *PathName,
1066     /* [out] */ DWORD *PathType,
1067     /* [in] */ DWORD Flags)
1068 {
1069     return ERROR_NOT_SUPPORTED;
1070 }
1071
1072 NET_API_STATUS NetprPathCanonicalize(
1073     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1074     /* [string][in] */ WCHAR *PathName,
1075     /* [size_is][out] */ unsigned char *Outbuf,
1076     /* [range][in] */ DWORD OutbufLen,
1077     /* [string][in] */ WCHAR *Prefix,
1078     /* [out][in] */ DWORD *PathType,
1079     /* [in] */ DWORD Flags)
1080 {
1081     return ERROR_NOT_SUPPORTED;
1082 }
1083
1084 long NetprPathCompare(
1085     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1086     /* [string][in] */ WCHAR *PathName1,
1087     /* [string][in] */ WCHAR *PathName2,
1088     /* [in] */ DWORD PathType,
1089     /* [in] */ DWORD Flags)
1090 {
1091     return ERROR_NOT_SUPPORTED;
1092 }
1093
1094 NET_API_STATUS NetprNameValidate(
1095     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1096     /* [string][in] */ WCHAR *Name,
1097     /* [in] */ DWORD NameType,
1098     /* [in] */ DWORD Flags)
1099 {
1100     return ERROR_NOT_SUPPORTED;
1101 }
1102
1103 NET_API_STATUS NetprNameCanonicalize(
1104     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1105     /* [string][in] */ WCHAR *Name,
1106     /* [size_is][out] */ WCHAR *Outbuf,
1107     /* [range][in] */ DWORD OutbufLen,
1108     /* [in] */ DWORD NameType,
1109     /* [in] */ DWORD Flags)
1110 {
1111     return ERROR_NOT_SUPPORTED;
1112 }
1113
1114 long NetprNameCompare(
1115     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1116     /* [string][in] */ WCHAR *Name1,
1117     /* [string][in] */ WCHAR *Name2,
1118     /* [in] */ DWORD NameType,
1119     /* [in] */ DWORD Flags)
1120 {
1121     return ERROR_NOT_SUPPORTED;
1122 }
1123
1124 NET_API_STATUS NetrShareEnumSticky(
1125     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1126     /* [out][in] */ LPSHARE_ENUM_STRUCT InfoStruct,
1127     /* [in] */ DWORD PreferedMaximumLength,
1128     /* [out] */ DWORD *TotalEntries,
1129     /* [unique][out][in] */ DWORD *ResumeHandle)
1130 {
1131     return ERROR_NOT_SUPPORTED;
1132 }
1133
1134 NET_API_STATUS NetrShareDelStart(
1135     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1136     /* [string][in] */ WCHAR *NetName,
1137     /* [in] */ DWORD Reserved,
1138     /* [out] */ PSHARE_DEL_HANDLE ContextHandle)
1139 {
1140     return ERROR_NOT_SUPPORTED;
1141 }
1142
1143 NET_API_STATUS NetrShareDelCommit(
1144     /* [out][in] */ PSHARE_DEL_HANDLE ContextHandle)
1145 {
1146     return ERROR_NOT_SUPPORTED;
1147 }
1148
1149 DWORD NetrpGetFileSecurity(
1150     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1151     /* [unique][string][in] */ WCHAR *ShareName,
1152     /* [string][in] */ WCHAR *lpFileName,
1153     /* [in] */ SECURITY_INFORMATION RequestedInformation,
1154     /* [out] */ PADT_SECURITY_DESCRIPTOR *SecurityDescriptor)
1155 {
1156     return ERROR_NOT_SUPPORTED;
1157 }
1158
1159 DWORD NetrpSetFileSecurity(
1160     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1161     /* [unique][string][in] */ WCHAR *ShareName,
1162     /* [string][in] */ WCHAR *lpFileName,
1163     /* [in] */ SECURITY_INFORMATION SecurityInformation,
1164     /* [in] */ PADT_SECURITY_DESCRIPTOR SecurityDescriptor)
1165 {
1166     return ERROR_NOT_SUPPORTED;
1167 }
1168
1169 NET_API_STATUS NetrServerTransportAddEx(
1170     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1171     /* [in] */ DWORD Level,
1172     /* [switch_is][in] */ LPTRANSPORT_INFO Buffer)
1173 {
1174     return ERROR_NOT_SUPPORTED;
1175 }
1176
1177 NET_API_STATUS NetrDfsGetVersion(
1178     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1179     /* [out] */ DWORD *Version)
1180 {
1181     return ERROR_NOT_SUPPORTED;
1182 }
1183
1184 NET_API_STATUS NetrDfsCreateLocalPartition(
1185     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1186     /* [string][in] */ WCHAR *ShareName,
1187     /* [in] */ GUID *EntryUid,
1188     /* [string][in] */ WCHAR *EntryPrefix,
1189     /* [string][in] */ WCHAR *ShortName,
1190     /* [in] */ LPNET_DFS_ENTRY_ID_CONTAINER RelationInfo,
1191     /* [in] */ int Force)
1192 {
1193     return ERROR_NOT_SUPPORTED;
1194 }
1195
1196 NET_API_STATUS NetrDfsDeleteLocalPartition(
1197     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1198     /* [in] */ GUID *Uid,
1199     /* [string][in] */ WCHAR *Prefix)
1200 {
1201     return ERROR_NOT_SUPPORTED;
1202 }
1203
1204 NET_API_STATUS NetrDfsSetLocalVolumeState(
1205     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1206     /* [in] */ GUID *Uid,
1207     /* [string][in] */ WCHAR *Prefix,
1208     /* [in] */ unsigned long State)
1209 {
1210     return ERROR_NOT_SUPPORTED;
1211 }
1212
1213 NET_API_STATUS NetrDfsCreateExitPoint(
1214     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1215     /* [in] */ GUID *Uid,
1216     /* [string][in] */ WCHAR *Prefix,
1217     /* [in] */ unsigned long Type,
1218     /* [range][in] */ DWORD ShortPrefixLen,
1219     /* [size_is][string][out] */ WCHAR *ShortPrefix)
1220 {
1221     return ERROR_NOT_SUPPORTED;
1222 }
1223
1224 NET_API_STATUS NetrDfsDeleteExitPoint(
1225     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1226     /* [in] */ GUID *Uid,
1227     /* [string][in] */ WCHAR *Prefix,
1228     /* [in] */ unsigned long Type)
1229 {
1230     return ERROR_NOT_SUPPORTED;
1231 }
1232
1233 NET_API_STATUS NetrDfsModifyPrefix(
1234     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1235     /* [in] */ GUID *Uid,
1236     /* [string][in] */ WCHAR *Prefix)
1237 {
1238     return ERROR_NOT_SUPPORTED;
1239 }
1240
1241 NET_API_STATUS NetrDfsFixLocalVolume(
1242     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1243     /* [string][in] */ WCHAR *VolumeName,
1244     /* [in] */ unsigned long EntryType,
1245     /* [in] */ unsigned long ServiceType,
1246     /* [string][in] */ WCHAR *StgId,
1247     /* [in] */ GUID *EntryUid,
1248     /* [string][in] */ WCHAR *EntryPrefix,
1249     /* [in] */ LPNET_DFS_ENTRY_ID_CONTAINER RelationInfo,
1250     /* [in] */ unsigned long CreateDisposition)
1251 {
1252     return ERROR_NOT_SUPPORTED;
1253 }
1254
1255 NET_API_STATUS NetrDfsManagerReportSiteInfo(
1256     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1257     /* [unique][out][in] */ LPDFS_SITELIST_INFO *ppSiteInfo)
1258 {
1259     return ERROR_NOT_SUPPORTED;
1260 }
1261
1262 NET_API_STATUS NetrServerTransportDelEx(
1263     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1264     /* [in] */ DWORD Level,
1265     /* [switch_is][in] */ LPTRANSPORT_INFO Buffer)
1266 {
1267     return ERROR_NOT_SUPPORTED;
1268 }
1269
1270 NET_API_STATUS NetrServerAliasAdd(
1271     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1272     /* [in] */ DWORD Level,
1273     /* [switch_is][in] */ LPSERVER_ALIAS_INFO InfoStruct)
1274 {
1275     return ERROR_NOT_SUPPORTED;
1276 }
1277
1278 NET_API_STATUS NetrServerAliasEnum(
1279     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1280     /* [out][in] */ LPSERVER_ALIAS_ENUM_STRUCT InfoStruct,
1281     /* [in] */ DWORD PreferedMaximumLength,
1282     /* [out] */ LPDWORD TotalEntries,
1283     /* [unique][out][in] */ LPDWORD ResumeHandle)
1284 {
1285     return ERROR_NOT_SUPPORTED;
1286 }
1287
1288 NET_API_STATUS NetrServerAliasDel(
1289     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1290     /* [in] */ DWORD Level,
1291     /* [switch_is][in] */ LPSERVER_ALIAS_INFO InfoStruct)
1292 {
1293     return ERROR_NOT_SUPPORTED;
1294 }
1295
1296 NET_API_STATUS NetrShareDelEx(
1297     /* [unique][string][in] */ SRVSVC_HANDLE ServerName,
1298     /* [in] */ DWORD Level,
1299     /* [switch_is][in] */ LPSHARE_INFO ShareInfo)
1300 {
1301     return ERROR_NOT_SUPPORTED;
1302 }
1303
1304
1305 void __RPC_USER SHARE_DEL_HANDLE_rundown( SHARE_DEL_HANDLE h)
1306 {
1307 }
1308
1309 /* [nocode] */ void Opnum0NotUsedOnWire(
1310     /* [in] */ handle_t IDL_handle)
1311 {
1312 }
1313
1314 /* [nocode] */ void Opnum1NotUsedOnWire(
1315     /* [in] */ handle_t IDL_handle)
1316 {
1317 }
1318
1319 /* [nocode] */ void Opnum2NotUsedOnWire(
1320     /* [in] */ handle_t IDL_handle)
1321 {
1322 }
1323
1324 #if 0
1325 /* [nocode] */ void Opnum3NotUsedOnWire(
1326     /* [in] */ handle_t IDL_handle)
1327 {
1328 }
1329
1330 /* [nocode] */ void Opnum4NotUsedOnWire(
1331     /* [in] */ handle_t IDL_handle)
1332 {
1333 }
1334 #endif
1335
1336 /* [nocode] */ void Opnum5NotUsedOnWire(
1337     /* [in] */ handle_t IDL_handle)
1338 {
1339 }
1340
1341 /* [nocode] */ void Opnum6NotUsedOnWire(
1342     /* [in] */ handle_t IDL_handle)
1343 {
1344 }
1345
1346 /* [nocode] */ void Opnum7NotUsedOnWire(
1347     /* [in] */ handle_t IDL_handle)
1348 {
1349 }
1350
1351 /* [nocode] */ void Opnum29NotUsedOnWire(
1352     /* [in] */ handle_t IDL_handle)
1353 {
1354 }
1355
1356 /* [nocode] */ void Opnum42NotUsedOnWire(
1357     /* [in] */ handle_t IDL_handle)
1358 {
1359 }
1360
1361 /* [nocode] */ void Opnum47NotUsedOnWire(
1362     /* [in] */ handle_t IDL_handle)
1363 {
1364 }
1365