NTSTATUS SrvFinderCreateSearchSpace( IN IO_FILE_HANDLE hRootFileHandle, IN PSRV_SHARE_INFO pShareInfo, IN PIO_CREATE_SECURITY_CONTEXT pIoSecurityContext, IN HANDLE hFinderRepository, IN PWSTR pwszFilesystemPath, IN PWSTR pwszSearchPattern, IN SMB_FILE_ATTRIBUTES usSearchAttrs, IN USHORT usFlags, IN ULONG ulSearchStorageType, IN SMB_INFO_LEVEL infoLevel, IN BOOLEAN bUseLongFilenames, IN ACCESS_MASK accessMask, OUT PHANDLE phFinder, OUT PUSHORT pusSearchId ) { NTSTATUS ntStatus = 0; IO_FILE_HANDLE hFile = NULL; IO_STATUS_BLOCK ioStatusBlock = {0}; IO_FILE_NAME fileName = {0}; PVOID pSecurityDescriptor = NULL; PVOID pSecurityQOS = NULL; PSRV_FINDER_REPOSITORY pFinderRepository = NULL; PSRV_SEARCH_SPACE pSearchSpace = NULL; USHORT usCandidateSearchId = 0; BOOLEAN bFound = FALSE; BOOLEAN bInLock = FALSE; PIO_ECP_LIST pEcpList = NULL; FILE_CREATE_OPTIONS createOptions = 0; pFinderRepository = (PSRV_FINDER_REPOSITORY)hFinderRepository; fileName.RootFileHandle = hRootFileHandle; ntStatus = LwRtlUnicodeStringInitEx(&fileName.Name, pwszFilesystemPath); BAIL_ON_NT_STATUS(ntStatus); if (pShareInfo->Flags & SHARE_INFO_FLAG_ABE_ENABLED) { ntStatus = IoRtlEcpListAllocate(&pEcpList); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvIoPrepareAbeEcpList(pEcpList); BAIL_ON_NT_STATUS(ntStatus); } if (usFlags & SMB_FIND_WITH_BACKUP_INTENT) { createOptions |= FILE_OPEN_FOR_BACKUP_INTENT; } ntStatus = SrvIoCreateFile( pShareInfo, &hFile, NULL, &ioStatusBlock, pIoSecurityContext, &fileName, pSecurityDescriptor, pSecurityQOS, accessMask, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, createOptions, NULL, /* EA Buffer */ 0, /* EA Length */ pEcpList); BAIL_ON_NT_STATUS(ntStatus); LWIO_LOCK_MUTEX(bInLock, &pFinderRepository->mutex); usCandidateSearchId = pFinderRepository->usNextSearchId; do { PSRV_SEARCH_SPACE pSearchSpace = NULL; // 0 is not a valid search id if (!usCandidateSearchId || (usCandidateSearchId == UINT16_MAX)) { usCandidateSearchId = 1; } ntStatus = LwRtlRBTreeFind( pFinderRepository->pSearchSpaceCollection, &usCandidateSearchId, (PVOID*)&pSearchSpace); if (ntStatus == STATUS_NOT_FOUND) { ntStatus = STATUS_SUCCESS; bFound = TRUE; } else { usCandidateSearchId++; } BAIL_ON_NT_STATUS(ntStatus); } while ((usCandidateSearchId != pFinderRepository->usNextSearchId) && !bFound); if (!bFound) { ntStatus = STATUS_TOO_MANY_OPENED_FILES; BAIL_ON_NT_STATUS(ntStatus); } ntStatus = SrvAllocateMemory( sizeof(SRV_SEARCH_SPACE), (PVOID*)&pSearchSpace); BAIL_ON_NT_STATUS(ntStatus); pSearchSpace->refCount = 1; pthread_mutex_init(&pSearchSpace->mutex, NULL); pSearchSpace->pMutex = &pSearchSpace->mutex; pSearchSpace->usSearchId = usCandidateSearchId; ntStatus = LwRtlRBTreeAdd( pFinderRepository->pSearchSpaceCollection, &pSearchSpace->usSearchId, pSearchSpace); BAIL_ON_NT_STATUS(ntStatus); pSearchSpace->hFile = hFile; hFile = NULL; pSearchSpace->infoLevel = infoLevel; pSearchSpace->usSearchAttrs = usSearchAttrs; pSearchSpace->ulSearchStorageType = ulSearchStorageType; pSearchSpace->bUseLongFilenames = bUseLongFilenames; ntStatus = SrvAllocateStringW( pwszSearchPattern, &pSearchSpace->pwszSearchPattern); BAIL_ON_NT_STATUS(ntStatus); InterlockedIncrement(&pSearchSpace->refCount); pFinderRepository->usNextSearchId = usCandidateSearchId + 1; *phFinder = pSearchSpace; *pusSearchId = usCandidateSearchId; cleanup: LWIO_UNLOCK_MUTEX(bInLock, &pFinderRepository->mutex); if (pEcpList) { IoRtlEcpListFree(&pEcpList); } return ntStatus; error: *phFinder = NULL; *pusSearchId = 0; if (pSearchSpace) { SrvFinderReleaseSearchSpace(pSearchSpace); } if (hFile) { IoCloseFile(hFile); } goto cleanup; }
static NTSTATUS SrvShareRegWriteToShareInfo( IN REG_DATA_TYPE regDataType, IN PWSTR pwszShareName, IN PBYTE pData, IN ULONG ulDataLen, IN REG_DATA_TYPE regSecDataType, IN PBYTE pSecData, IN ULONG ulSecDataLen, OUT PSRV_SHARE_INFO* ppShareInfo ) { NTSTATUS ntStatus = STATUS_SUCCESS; PSRV_SHARE_INFO pShareInfo = NULL; PWSTR* ppwszValues = NULL; PSTR pszFlags = NULL; ntStatus = SrvAllocateMemory(sizeof(*pShareInfo), (PVOID*)&pShareInfo); BAIL_ON_NT_STATUS(ntStatus); pShareInfo->refcount = 1; pthread_rwlock_init(&pShareInfo->mutex, NULL); pShareInfo->pMutex = &pShareInfo->mutex; ntStatus = SrvAllocateStringW(pwszShareName, &pShareInfo->pwszName); BAIL_ON_NT_STATUS(ntStatus); if (pData) { ULONG iValue = 0; wchar16_t wszCommentPrefix[] = REG_KEY_COMMENT_PREFIX_W; ULONG ulCommentPrefixLen = (sizeof(wszCommentPrefix)/sizeof(wchar16_t)) - 1; wchar16_t wszPathPrefix[] = REG_KEY_PATH_PREFIX_W; ULONG ulPathPrefixLen = (sizeof(wszPathPrefix)/sizeof(wchar16_t)) - 1; wchar16_t wszServicePrefix[] = REG_KEY_SERVICE_PREFIX_W; ULONG ulServicePrefixLen = (sizeof(wszServicePrefix)/sizeof(wchar16_t)) - 1; wchar16_t wszFlagsPrefix[] = REG_KEY_FLAGS_PREFIX_W; ULONG ulFlagsPrefixLen = (sizeof(wszFlagsPrefix)/sizeof(wchar16_t)) - 1; ntStatus = NtRegByteArrayToMultiStrs(pData, ulDataLen, &ppwszValues); BAIL_ON_NT_STATUS(ntStatus); for (; ppwszValues[iValue]; iValue++) { PWSTR pwszValue = &ppwszValues[iValue][0]; if (!wc16sncmp(&wszPathPrefix[0], pwszValue, ulPathPrefixLen)) { SRV_SAFE_FREE_MEMORY(pShareInfo->pwszPath); ntStatus = SrvAllocateStringW( &pwszValue[ulPathPrefixLen], &pShareInfo->pwszPath); BAIL_ON_NT_STATUS(ntStatus); } else if (!wc16sncmp(&wszCommentPrefix[0], pwszValue, ulCommentPrefixLen)) { SRV_SAFE_FREE_MEMORY(pShareInfo->pwszComment); ntStatus = SrvAllocateStringW( &pwszValue[ulCommentPrefixLen], &pShareInfo->pwszComment); BAIL_ON_NT_STATUS(ntStatus); } else if (!wc16sncmp(&wszServicePrefix[0], pwszValue, ulServicePrefixLen)) { ntStatus = SrvShareMapServiceStringToIdW( &pwszValue[ulServicePrefixLen], &pShareInfo->service); BAIL_ON_NT_STATUS(ntStatus); } else if (!wc16sncmp(&wszFlagsPrefix[0], pwszValue, ulFlagsPrefixLen)) { ntStatus = RtlCStringAllocateFromWC16String( &pszFlags, &pwszValue[ulFlagsPrefixLen]); BAIL_ON_NT_STATUS(ntStatus); pShareInfo->ulFlags = strtol(pszFlags, NULL, 16); } else { ntStatus = STATUS_INVALID_PARAMETER_3; BAIL_ON_NT_STATUS(ntStatus); } } } if (!pShareInfo->pwszComment) { wchar16_t wszComment[] = {0}; ntStatus = SrvAllocateStringW( &wszComment[0], &pShareInfo->pwszComment); BAIL_ON_NT_STATUS(ntStatus); } if (ulSecDataLen) { ntStatus = SrvShareSetSecurity( pShareInfo, (PSECURITY_DESCRIPTOR_RELATIVE)pSecData, ulSecDataLen); BAIL_ON_NT_STATUS(ntStatus); } else { ntStatus = SrvShareSetDefaultSecurity(pShareInfo); BAIL_ON_NT_STATUS(ntStatus); } *ppShareInfo = pShareInfo; cleanup: if (ppwszValues) { RegFreeMultiStrsW(ppwszValues); } RTL_FREE(&pszFlags); return ntStatus; error: if (pShareInfo) { SrvShareReleaseInfo(pShareInfo); } goto cleanup; }
NTSTATUS SrvFinderBuildSearchPath( IN PWSTR pwszPath, IN PWSTR pwszSearchPattern, OUT PWSTR* ppwszFilesystemPath, OUT PWSTR* ppwszSearchPattern, IN OUT OPTIONAL PBOOLEAN pbPathHasWildCards ) { NTSTATUS ntStatus = 0; wchar16_t wszStar[] = {'*', 0}; wchar16_t wszBackslash[] = {'\\', 0}; wchar16_t wszQuestionMark[] = {'?', 0}; wchar16_t wszQuote[] = {'\"', 0}; wchar16_t wszGT[] = {'>', 0}; wchar16_t wszLT[] = {'<', 0}; wchar16_t wszDot[] = {'.', 0}; size_t sLen = 0; PWSTR pwszCursor = NULL; PWSTR pwszLastSlash = NULL; PWSTR pwszFilesystemPath = NULL; PWSTR pwszSearchPattern3 = NULL; PWSTR pwszSearchPattern2 = NULL; BOOLEAN bPathHasWildCards = FALSE; sLen = IsNullOrEmptyString(pwszPath) ? 0 : wc16slen(pwszPath); while (pwszSearchPattern && *pwszSearchPattern && (*pwszSearchPattern == wszBackslash[0])) { pwszSearchPattern++; } if (pwszSearchPattern && *pwszSearchPattern) { ntStatus = SrvAllocateStringW(pwszSearchPattern, &pwszSearchPattern3); BAIL_ON_NT_STATUS(ntStatus); } pwszCursor = pwszSearchPattern3; while (pwszCursor && *pwszCursor) { if (*pwszCursor == wszGT[0]) { bPathHasWildCards = TRUE; *pwszCursor = wszQuestionMark[0]; } else if (*pwszCursor == wszQuote[0]) { PWSTR pwszNext = pwszCursor; pwszNext++; if (!pwszNext || ((*pwszNext == wszQuestionMark[0] || *pwszNext == wszStar[0] || *pwszNext == wszGT[0] || *pwszNext == wszLT[0] || *pwszNext == wszQuote[0]))) { bPathHasWildCards = TRUE; *pwszCursor = wszDot[0]; } } else if (*pwszCursor == wszLT[0]) { PWSTR pwszNext = pwszCursor; bPathHasWildCards = TRUE; pwszNext++; if (pwszNext || (((*pwszNext == wszDot[0]) || (*pwszNext == wszQuote[0]) || (*pwszNext == wszLT[0])))) { *pwszCursor = wszStar[0]; } } pwszCursor++; } pwszCursor = pwszSearchPattern3; while (pwszCursor && *pwszCursor) { if (*pwszCursor == wszBackslash[0]) { pwszLastSlash = pwszCursor; } else if ((*pwszCursor == wszStar[0]) || (*pwszCursor == wszQuestionMark[0])) { bPathHasWildCards = TRUE; break; } pwszCursor++; } if (pwszLastSlash) { PBYTE pDataCursor = NULL; size_t sSuffixLen = 0; sSuffixLen = ((PBYTE)pwszLastSlash - (PBYTE)pwszSearchPattern3); ntStatus = SrvAllocateMemory( sLen * sizeof(wchar16_t) + sizeof(wszBackslash[0]) + sSuffixLen + sizeof(wchar16_t), (PVOID*)&pwszFilesystemPath); BAIL_ON_NT_STATUS(ntStatus); pDataCursor = (PBYTE)pwszFilesystemPath; if (sLen) { memcpy(pDataCursor, (PBYTE)pwszPath, sLen * sizeof(wchar16_t)); pDataCursor += sLen * sizeof(wchar16_t); } *((wchar16_t*)pDataCursor) = wszBackslash[0]; pDataCursor += sizeof(wszBackslash[0]); memcpy(pDataCursor, pwszSearchPattern, sSuffixLen); } else if (pwszPath) { ntStatus = SrvAllocateStringW( pwszPath, &pwszFilesystemPath); BAIL_ON_NT_STATUS(ntStatus); } pwszCursor = (pwszLastSlash ? ++pwszLastSlash : pwszSearchPattern3); if (pwszCursor && *pwszCursor) { ntStatus = SrvAllocateStringW(pwszCursor, &pwszSearchPattern2); } else { ntStatus = SrvAllocateStringW(wszStar, &pwszSearchPattern2); } BAIL_ON_NT_STATUS(ntStatus); *ppwszFilesystemPath = pwszFilesystemPath; *ppwszSearchPattern = pwszSearchPattern2; if (pbPathHasWildCards) { *pbPathHasWildCards = bPathHasWildCards; } cleanup: SRV_SAFE_FREE_MEMORY(pwszSearchPattern3); return ntStatus; error: *ppwszFilesystemPath = NULL; *ppwszSearchPattern = NULL; if (pbPathHasWildCards) { *pbPathHasWildCards = FALSE; } SRV_SAFE_FREE_MEMORY(pwszFilesystemPath); SRV_SAFE_FREE_MEMORY(pwszSearchPattern2); goto cleanup; }