//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1996 - 1996. // // File: cmd.cxx // // Contents: Command-line operations // // History: 7-May-96 BruceFo Created // //-------------------------------------------------------------------------- #include "headers.hxx" #pragma hdrstop #include #include "cmd.hxx" #include "myutil.hxx" ULONG DfscmdPrintf( PWCHAR format, ...); // // -- create intermediate directories // -- don't remove if it's the last one // -- // This function determines where the server and share name are in a UNC path, // and sets them to the output parameters. Note that the input parameter is // munged in the process. E.g.: // input: \\brucefo4\root\hello // output: \\brucefo4\0root\hello // ^server ^share // // FALSE is returned if it doesn't appear to be a UNC path. TRUE is returned // if everything seems ok. BOOL GetServerShare( IN OUT PWSTR pszUncPath, OUT PWSTR* ppszServer, OUT PWSTR* ppszShare ) { appAssert(NULL != pszUncPath); // // Do a quick check that this is a UNC path // PWSTR pT; if ( L'\\' != pszUncPath[0] || L'\\' != pszUncPath[1] || L'\\' == pszUncPath[2] || L'\0' == pszUncPath[2] || (NULL == (pT = wcschr(&pszUncPath[3], L'\\'))) ) { return FALSE; } *ppszServer = &pszUncPath[2]; *pT++ = L'\0'; *ppszShare = pT; appDebugOut((DEB_TRACE, "GetServerShare: Server: %ws, share: %ws\n", *ppszServer, *ppszShare)); return TRUE; } // This function determines the appropriate Dfs name to pass to the NetDfs // APIs. The input buffer is modified. E.g.: // input: \\dfsname\dfsshare // output: \\dfsname\0dfsshare // ^dfs // // FALSE is returned if it doesn't appear to be a dfs name. TRUE is returned // if everything seems ok. BOOL GetDfs( IN OUT PWSTR pszDfsName, OUT PWSTR* ppszDfs ) { appAssert(NULL != pszDfsName); // // Do a quick check that this is a Dfs name // PWSTR pT; if ( L'\\' != pszDfsName[0] || L'\\' != pszDfsName[1] || L'\\' == pszDfsName[2] || L'\0' == pszDfsName[2] || (NULL == (pT = wcschr(&pszDfsName[3], L'\\'))) ) { return FALSE; } *ppszDfs = &pszDfsName[2]; // // Go to next slash or end // pT++; while (*pT != L'\\' && *pT != L'\0') pT++; *pT = L'\0'; appDebugOut((DEB_TRACE, "GetDfs: Dfs: %ws\n", *ppszDfs)); return TRUE; } VOID CmdMap( IN PWSTR pszDfsPath, IN PWSTR pszUncPath, IN PWSTR pszComment, IN BOOLEAN fRestore ) { appDebugOut((DEB_TRACE,"CmdMap(%ws, %ws, %ws)\n", pszDfsPath, pszUncPath, pszComment)); PWSTR pszServer, pszShare; if (!GetServerShare(pszUncPath, &pszServer, &pszShare)) { Usage(); } NET_API_STATUS status = NetDfsAdd( pszDfsPath, pszServer, pszShare, pszComment, (fRestore == FALSE) ? DFS_ADD_VOLUME : DFS_ADD_VOLUME | DFS_RESTORE_VOLUME); if (status == NERR_Success) { // Notify shell of change. appDebugOut((DEB_TRACE, "Notify shell about new path %ws\n", pszDfsPath)); SHChangeNotify(SHCNE_MKDIR, SHCNF_PATH, pszDfsPath, NULL); } else { DfsErrorMessage(status); } } VOID CmdUnmap( IN PWSTR pszDfsPath ) { appDebugOut((DEB_TRACE,"CmdUnmap(%ws)\n", pszDfsPath)); // // Delete all the replicas, and hence the volume // HRESULT hr = S_OK; PDFS_INFO_3 pVolumeInfo = NULL; NET_API_STATUS status = NetDfsGetInfo( pszDfsPath, NULL, NULL, 3, (LPBYTE*)&pVolumeInfo); CHECK_NET_API_STATUS(status); if (NERR_Success == status) { // now, we have pVolumeInfo memory to delete for (ULONG i = 0; i < pVolumeInfo->NumberOfStorages; i++) { appDebugOut((DEB_TRACE, "Deleting replica %d of %d\n", i + 1, pVolumeInfo->NumberOfStorages)); PDFS_STORAGE_INFO pDfsStorageInfo = &pVolumeInfo->Storage[i]; status = NetDfsRemove( pszDfsPath, pDfsStorageInfo->ServerName, pDfsStorageInfo->ShareName); if (status != NERR_Success) { DfsErrorMessage(status); } } NetApiBufferFree(pVolumeInfo); } else { DfsErrorMessage(status); } // Notify shell of change. appDebugOut((DEB_TRACE, "Notify shell about deleted path %ws\n", pszDfsPath)); SHChangeNotify(SHCNE_RMDIR, SHCNF_PATH, pszDfsPath, NULL); } VOID CmdAdd( IN PWSTR pszDfsPath, IN PWSTR pszUncPath, IN BOOLEAN fRestore ) { appDebugOut((DEB_TRACE,"CmdAdd(%ws, %ws)\n", pszDfsPath, pszUncPath)); PWSTR pszServer, pszShare; if (!GetServerShare(pszUncPath, &pszServer, &pszShare)) { Usage(); } NET_API_STATUS status = NetDfsAdd( pszDfsPath, pszServer, pszShare, NULL, (fRestore == FALSE) ? 0 : DFS_RESTORE_VOLUME); if (status != NERR_Success) { DfsErrorMessage(status); } } VOID CmdRemove( IN PWSTR pszDfsPath, IN PWSTR pszUncPath ) { appDebugOut((DEB_TRACE,"CmdRemove(%ws, %ws)\n", pszDfsPath, pszUncPath)); PWSTR pszServer, pszShare; if (!GetServerShare(pszUncPath, &pszServer, &pszShare)) { Usage(); } NET_API_STATUS status = NetDfsRemove( pszDfsPath, pszServer, pszShare); if (status != NERR_Success) { DfsErrorMessage(status); } } VOID CmdView( IN PWSTR pszDfsName, // of form \\dfsname\dfsshare IN DWORD level, IN BOOLEAN fBatch, IN BOOLEAN fRestore ) { appDebugOut((DEB_TRACE,"CmdView(%ws, %d)\n", pszDfsName, level)); PWSTR pszDfs; // of form 'dfsname' if (!GetDfs(pszDfsName, &pszDfs)) { Usage(); } DWORD entriesread; LPBYTE buffer; DWORD resumeHandle = 0; NET_API_STATUS status = NetDfsEnum( pszDfs, level, 0xffffffff, (LPBYTE*)&buffer, &entriesread, &resumeHandle); if (status == NERR_Success) { PDFS_INFO_3 pDfsInfo = (PDFS_INFO_3)buffer; DWORD i, j; LPDFS_STORAGE_INFO pStorage; #if DBG == 1 appDebugOut((DEB_TRACE,"NetDfsEnum returned %d entries\n", entriesread)); for (i = 0; i < entriesread; i++) { if (level == 1) { pDfsInfo = (PDFS_INFO_3)(&(((PDFS_INFO_1)buffer)[i])); } else if (level == 2) { pDfsInfo = (PDFS_INFO_3)(&(((PDFS_INFO_2)buffer)[i])); } else if (level == 3) { pDfsInfo = &(((PDFS_INFO_3)buffer)[i]); } else { // bug! break; } appDebugOut((DEB_TRACE,"\t%ws\n", pDfsInfo->EntryPath)); } pDfsInfo = (PDFS_INFO_3)buffer; #endif // DBG == 1 if (fBatch == FALSE) { for (i = 0; i < entriesread; i++) { DfscmdPrintf(L"%ws", pDfsInfo->EntryPath); if (level == 1) { DfscmdPrintf(L"\r\n"); pDfsInfo = (LPDFS_INFO_3) ((LPBYTE) pDfsInfo + sizeof(DFS_INFO_1)); continue; } if (L'\0' != *pDfsInfo->Comment) { // Print the comment at column 60. int len = wcslen(pDfsInfo->EntryPath); while (len++ < 58) { DfscmdPrintf(L" "); // putchar? } DfscmdPrintf(L" %ws\r\n", pDfsInfo->Comment); } else { DfscmdPrintf(L"\r\n"); } if (level == 2) { pDfsInfo = (LPDFS_INFO_3) ((LPBYTE) pDfsInfo + sizeof(DFS_INFO_2)); continue; } pStorage = pDfsInfo->Storage; for (j = 0; j < pDfsInfo->NumberOfStorages; j++) { DfscmdPrintf(L"\t\\\\%ws\\%ws\r\n", pStorage[j].ServerName, pStorage[j].ShareName); } pDfsInfo = (LPDFS_INFO_3) ((LPBYTE) pDfsInfo + sizeof(DFS_INFO_3)); } } else { DfscmdPrintf(L"REM BATCH RESTORE SCRIPT\r\n\r\n"); for (i = 0; i < entriesread; i++) { pStorage = pDfsInfo->Storage; for (j = 0; j < pDfsInfo->NumberOfStorages; j++) { if (pDfsInfo->Comment == NULL || j > 0 || (wcslen(pDfsInfo->Comment) == 1 && pDfsInfo->Comment[0] == L' ') ) { DfscmdPrintf(L"%wsdfscmd /%ws \"%ws\" \"\\\\%ws\\%ws\"%ws\r\n", (i == 0) ? L"REM " : L"", (j == 0) ? L"map" : L"add", pDfsInfo->EntryPath, pStorage[j].ServerName, pStorage[j].ShareName, (fRestore == TRUE) ? L" /restore" : L""); } else { DfscmdPrintf(L"%wsdfscmd /%ws \"%ws\" \"\\\\%ws\\%ws\" \"%ws\"%ws\r\n", (i == 0) ? L"REM " : L"", (j == 0) ? L"map" : L"add", pDfsInfo->EntryPath, pStorage[j].ServerName, pStorage[j].ShareName, pDfsInfo->Comment, (fRestore == TRUE) ? L" /restore" : L""); } } DfscmdPrintf(L"\r\n"); pDfsInfo = (LPDFS_INFO_3) ((LPBYTE) pDfsInfo + sizeof(DFS_INFO_3)); } } NetApiBufferFree( buffer ); } else { DfsErrorMessage(status); } } // // The following is copied from dfsutil code, which allows redirection of // output to a file. // #define MAX_MESSAGE_BUF 4096 #define MAX_ANSI_MESSAGE_BUF (MAX_MESSAGE_BUF * 3) WCHAR MsgBuf[MAX_MESSAGE_BUF]; CHAR AnsiBuf[MAX_ANSI_MESSAGE_BUF]; ULONG DfscmdPrintf( PWCHAR format, ...) { DWORD written; va_list va; va_start(va, format); wvsprintf(MsgBuf, format, va); written = WideCharToMultiByte(CP_OEMCP, 0, MsgBuf, wcslen(MsgBuf), AnsiBuf, MAX_ANSI_MESSAGE_BUF, NULL, NULL); WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), AnsiBuf, written, &written, NULL); va_end(va); return written; } #ifdef MOVERENAME VOID CmdMove( IN PWSTR pszDfsPath1, IN PWSTR pszDfsPath2 ) { appDebugOut((DEB_TRACE,"CmdMove(%ws, %ws)\n", pszDfsPath1, pszDfsPath2)); NET_API_STATUS status = NetDfsMove( pszDfsPath1, pszDfsPath2); if (status != NERR_Success) { DfsErrorMessage(status); } } VOID CmdRename( IN PWSTR pszPath, IN PWSTR pszNewPath ) { appDebugOut((DEB_TRACE,"CmdRename(%ws, %ws)\n", pszPath, pszNewPath)); NET_API_STATUS status = NetDfsRename( pszPath, pszNewPath); if (status != NERR_Success) { DfsErrorMessage(status); } } #endif